﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Data;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace TestMySqlConnetPoll
{
    public class objKglReplayStruct
    {
        public int stime = 0;           //开关量开始时间
        public int etime = 0;               //开关量结束时间
        public int AllRecordNum = 0;        //总记录数
        public int KGLNum = 0;              //开关量总路数
        public int wholeKGLRecordNum = 0;   //全体开关量记录数
        //public List<int> kglIdx = new List<int>();    //开关量索引
        //public List<byte> ValueList = new List<byte>(); //开关量记录
        public List<objRevKGL> KGL_ValueList = new List<objRevKGL>();
    }

    public struct objRecordCurveKey
    {
        public DateTime time;      //时间
        public byte DevType;       //设备类型
        public int DevNo;          //设备号
    }

    public struct objHistoryAlaramKey
    {
        public objDate date;
        public byte AlarmType;
    }

    public static class c_NetData
    {
        /// <summary>
        /// 对象克隆函数，用户两个完全相等的对象的克隆
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static object Clone(object obj)
        {
            MemoryStream memoryStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memoryStream, obj);
            memoryStream.Position = 0;
            return formatter.Deserialize(memoryStream);
        }

        public struct objNetCode
        {
            public string sCode;
            public byte type;
            public byte sontype; //子类型
            public int utime;
            public int DevNo; //设备号
            public int stime; //开始时间
            public int etime; //结束时间
            public int recallNum;
            public int recallstime; //重复开始时间
            public int recalletime; //重复结束时间            
        }

        public class objNetAnalogReplay
        {
            public string sCode = "";
            public int stime = 0; //开始时间
            public int etime = 0; //结束时间
            public int recallNum = 0;
            public int recallstime = 0; //重复开始时间
            public int recalletime = 0; //重复结束时间
            public int analogNum = 0;   //模拟量数目
            public List<byte> AnalogSet = new List<byte>(); //模拟量类型集合
        }

        public struct objTimeRecall
        {
            public int rNum;
            public int stime;
            public int etime;
            public int srecalltime;
            public int erecalltime;
        }        

        #region 站机变量
        /// <summary>
        /// 系统的时间重叠时间表,站机记录
        /// </summary>
        public static Dictionary<objDate, List<objTimeAdjust>> DayTimeAdjust_station = new Dictionary<objDate, List<objTimeAdjust>>();
        /// <summary>
        /// 站机从数据库读取的日曲线值列表,跟时间一起使用，如果时间不相同，则清除数据缓冲区
        /// 终端调阅日曲线时，不能一次全取，一般分两次取，为了不读两次数据库，则把一次取出来的数据放入到该缓冲区中.
        /// </summary>
        private static Dictionary<objCodeDev, List<objTimeValue>> StationDailyCurveValueList = new Dictionary<objCodeDev, List<objTimeValue>>();
        private static DateTime StationDailyCurveDay = new DateTime();
        #endregion
        #region 终端变量
        public static event EventHandler NewLKEvent;
        public static event EventHandler NewAlarmEvent;
        public static event EventHandler EventRevSevAlarmRet;
        /// <summary>
        /// 从网络获取的日报表时间列表
        /// </summary>
        public static List<DateTime> DailyReportTimeList = new List<DateTime>();    //日报表时间命令
        /// <summary>
        /// 从网络读取的日报表数据
        /// </summary>
        public static Dictionary<byte, List<objDailyReport>> DailyReportAnalogValueList = new Dictionary<byte, List<objDailyReport>>();
        /// <summary>
        /// 从网络获取的日曲线时间列表
        /// </summary>
        public static List<DateTime> DailyCurveTimeList = new List<DateTime>();
       
        /// <summary>
        /// 从网络获取的日曲线值列表,分上午和下午的数据，终端点击获取日曲线时清除，判断跟当前缓冲区的非一天时，清除该数据.
        /// </summary>
        public static Dictionary<objCodeDev, List<objTimeValue>> TermianlAmDailyCurveValueList = new Dictionary<objCodeDev, List<objTimeValue>>();
        public static Dictionary<objCodeDev, List<objTimeValue>> TermianlPmDailyCurveValueList = new Dictionary<objCodeDev, List<objTimeValue>>();
        public static objDate TerminalDailyCurveDay = new objDate();
        /// <summary>
        /// 从网络获取的日曲线回溯段时间
        /// </summary>
        public static objTimeRecall TerminalDailyAmCurveRecallTime = new objTimeRecall(); //上午的回溯
        public static objTimeRecall TerminalDailyPmCurveRecallTime = new objTimeRecall(); //下午的回溯


        /// <summary>
        /// 站机从数据库读取的高频日曲线值列表,跟时间一起使用，如果时间不相同，则清除数据缓冲区
        /// 终端调阅高频日曲线时，不能一次全取，一般分两次取，为了不读两次数据库，则把一次取出来的数据放入到该缓冲区中.
        /// </summary>
        private static Dictionary<objCodeDev, List<HigFreAnalogValue>> StationDailyHigFrequencyValueList = new Dictionary<objCodeDev, List<HigFreAnalogValue>>();
        private static DateTime StationDailyHigFrequencyDay = new DateTime();

        /// <summary>
        /// 从网络获取的高频日曲线值列表,分上午和下午的数据，终端点击获取日曲线时清除，判断跟当前缓冲区的非一天时，清除该数据.
        /// </summary>
        public static Dictionary<objCodeDev, List<HigFreAnalogValue>> TermianlAmDailyHigCurveValueList = new Dictionary<objCodeDev, List<HigFreAnalogValue>>();
        public static Dictionary<objCodeDev, List<HigFreAnalogValue>> TermianlPmDailyHigCurveValueList = new Dictionary<objCodeDev, List<HigFreAnalogValue>>();
        public static objDate TerminalDailyHigCurveDay = new objDate();
        /// <summary>
        /// 从网络获取的高频日曲线回溯段时间
        /// </summary>
        public static objTimeRecall TerminalDailyAmHigCurveRecallTime = new objTimeRecall(); //上午的回溯
        public static objTimeRecall TerminalDailyPmHigCurveRecallTime = new objTimeRecall(); //下午的回溯

        public static int KGLReplayStime = 0;   //开关量回放有效时间
        public static int KGLReplayEtime = 0;   //开关量回放有效结束时间
        public static int KGLRecallStime = 0;   //开关量回溯开始时间
        public static int KGLRecallEtime = 0;   //开关量回溯结束时间
        public static int KGLRecallRum = 0;     //开关量回溯次数

        /// <summary>
        /// 开关量回放数据
        /// </summary>
        ///public static objKglReplayStruct TerminalReplayKglValue = new objKglReplayStruct();
        public static List<byte> TerminalReplayKglValue = new List<byte>();     //接收到的开关量数据，原始数据,可以直接写成文件的数据
        static public objKglReplayStruct TerminalReplayKglValueTidy = new objKglReplayStruct();      //终端接收到的开关量值，从缓冲区转换过后的值,全是全体开关量数据
        /// <summary>
        /// 终端接收到的模拟量回放数据，原始数据，可以写成文件的数据
        /// </summary>
        public static List<byte> TerminalReplayAnalogValue = new List<byte>();
        /// <summary>
        /// 终端接收到的模拟量回放数据，按模拟量类型组织好.
        /// </summary>
        public static Dictionary<AnalogCodeType, List<ReplayClass>> TerminalReplayAnalogValueTidy = new Dictionary<AnalogCodeType, List<ReplayClass>>(); 
        /// <summary>
        /// 高频模拟量回放数据，网络接收到的数据，可以写成文件的数据
        /// </summary>
        public static List<byte> TerminalReplayHighFrequencyValue = new List<byte>();
        /// <summary>
        /// 高频模拟量回放数据，按照模拟量类型整理好的缓冲区
        /// </summary>
        public static Dictionary<AnalogCodeType, List<HighReplayClass>> TerminalReplayHighFrequencyValueTidy = new Dictionary<AnalogCodeType, List<HighReplayClass>>(); 
        /// <summary>
        /// 收到的开关量实时值包序号
        /// </summary>
        public static int RevKglTick = 1;
        /// <summary>
        /// 接收到的开关量历史数据，原始数据，加整理过后的数据
        /// </summary>
        public static List<byte> TerminalHistoryKglValue = new List<byte>();     //接收到的开关量数据，原始数据,可以直接写成文件的数据
        static public objKglReplayStruct TerminalHistoryKglValueTidy = new objKglReplayStruct();      //终端接收到的开关量值，从缓冲区转换过后的值,全是全体开关量数据
        /// <summary>
        /// 记录曲线的时间列表，只要换设备就清除该列表
        /// </summary>
        public static List<DateTime> TerminalRecordCurveTimeList = new List<DateTime>();

        public static Dictionary<objRecordCurveKey, ObjDcdlType> TerminalDcdlqxValueList = new Dictionary<objRecordCurveKey, ObjDcdlType>();   //道岔电流曲线
        public static Dictionary<objRecordCurveKey, ObjDcdlType> TerminalDcdzCKqxValueList = new Dictionary<objRecordCurveKey, ObjDcdlType>(); //道岔动作参考曲线,
        public static Dictionary<objRecordCurveKey, ObjDcdlType> TerminalDcdzMcqxValueList = new Dictionary<objRecordCurveKey, ObjDcdlType>(); //道岔动作摩擦曲线
        public static Dictionary<objRecordCurveKey, ObjGybdcType> TerminalGybdcValueList = new Dictionary<objRecordCurveKey, ObjGybdcType>(); //高压不对称曲线
        /// <summary>
        /// 终端接收的统计数据
        /// </summary>
        public static Dictionary<objTongJiKey, List<objTongJiReport>> TerminalTongJiValueList = new Dictionary<objTongJiKey, List<objTongJiReport>>();

        ///static public Dictionary<byte, List<ObjAlaram>> TerminalRealTimeAlarmData = new Dictionary<byte, List<ObjAlaram>>();
        ///终端收到的报警信息时间列表
        static public Dictionary<byte, List<DateTime>> TerminalAlarmTimeList = new Dictionary<byte, List<DateTime>>();
        /// <summary>
        /// 终端收到的历史报警信息
        /// </summary>
        static public Dictionary<objHistoryAlaramKey, List<ObjAlaram>> TerminalAlarmValueList = new Dictionary<objHistoryAlaramKey, List<ObjAlaram>>();
        #region 终端列控变量
        static public DateTime TerminalLkHistoryStartTime = new DateTime();
        static public DateTime TerminalLkHistoryEndTime = new DateTime();
        static public DataSet HostHardwarePlatform_ASet = new DataSet("列控中心主机硬件平台A机");
        static public DataSet HostHardwarePlatform_BSet = new DataSet("列控中心主机硬件平台B机");
        static public DataTable LianSuoJieKouRouteInfo = new DataTable("列控中心与联锁接口进路信息");
        static public DataTable LianSuoGaiFangCommandInfo = new DataTable("列控中心与联锁改方命令信息");
        static public DataTable LianSuoGaiFangCommandRet = new DataTable("列控中心与联锁改方回执信息");
        static public DataTable ZhanJianGaiFangCommandInfo = new DataTable("列控中心站间改方命令信息");
        static public DataTable ZhanJianGaiFangCommandRet = new DataTable("列控中心站间改方回执信息");
        static public DataTable ZhanJianBoundaryInfo = new DataTable("列控中心站间边界信息");
        static public DataTable SendToLianSuoInfo = new DataTable("发送给联锁的无配线站区间方向口信息");
        static public DataTable TemporaryLimitSpeedState = new DataTable("列控中心临时限速状态");
        static public DataSet SectionEncodeInfo = new DataSet("轨道区段编码信息");
        static public DataTable TransponderEncodeInfo = new DataTable("应答器报文编码信息");
        static public Dictionary<DateTime, DataSet> AllStatueInfo = new Dictionary<DateTime, DataSet>();   //全体状态信息
        #endregion
        #endregion
        /// <summary>
        /// 获取当前的时间重叠记录 ，非立即返回函数，调用该函数时，需使用线程池调用
        /// 返回1表示正确，0表示错误.
        /// </summary>
        /// <param name="d"></param>
        public static int ThreadGetTimeAdjustRecord(objDate day)
        {            
            DateTime today = DateTime.Now;
            ///当天的都应该查数据库.            
            if (today.Year == day.year && today.Month == day.month && today.Day == day.day)
            {
            }
            else if (DayTimeAdjust_station.Keys.Contains(day))
            {
                return 1;   //直接返回
            }
            TimeAdjustTable tbhs = new TimeAdjustTable();
            tbhs.ReadValueList();
            while (true)
            {
                if (tbhs.ErrorFlag != 0)  return  0; //错误
                else if (tbhs.ReadyValueList)
                {
                    for (int i = 0; i < tbhs.ValueList.Count; i++)
                    {
                        objTimeAdjust obj = new objTimeAdjust();
                        obj.btime = tbhs.ValueList[i].btime;
                        obj.ftime = tbhs.ValueList[i].ftime;

                        objDate t = MySql.Time_tToObjDate(obj.btime);
                        
                        if (DayTimeAdjust_station.Keys.Contains(t))
                        {
                            DayTimeAdjust_station[t].Add(obj);
                        }
                        else
                        {
                            List<objTimeAdjust> li = new List<objTimeAdjust>();
                            li.Add(obj);
                            DayTimeAdjust_station.Add(t, li);
                        }
                    }
                    break;
                }
                else Thread.Sleep(300);
            }
            return 1;
        }

        public static void InitNetData()
        {
            c_NetCom.Event_OneNetComData +=new EventHandler(c_NetCom_Event_OneNetComData);

            c_LK.InitLianSuoGaiFangCommandInfo(ref LianSuoGaiFangCommandInfo);
            c_LK.InitLianSuoGaiFangCommandRet(ref LianSuoGaiFangCommandRet);
            c_LK.InitLianSuoJieKouRouteInfo(ref LianSuoJieKouRouteInfo);            
            c_LK.InitSendToLianSuoInfo(ref SendToLianSuoInfo);
            c_LK.InitTemporaryLimitSpeedState(ref TemporaryLimitSpeedState);
            c_LK.InitTransponderEncodeInfo(ref TransponderEncodeInfo);
            c_LK.InitZhanJianBoundaryInfo(ref ZhanJianBoundaryInfo);
            c_LK.InitZhanJianGaiFangCommandInfo(ref ZhanJianGaiFangCommandInfo);
            c_LK.InitZhanJianGaiFangCommandRet(ref ZhanJianGaiFangCommandRet);
        }

        /// <summary>
        /// 网络数据处理线程
        /// </summary>
        public static void c_NetCom_Event_OneNetComData(object sender,EventArgs e)
        {
            objProtecol obj = (objProtecol)sender;
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadDisposeNetCmd), obj);
        }

        public static void ThreadDisposeNetCmd(object obj)
        {
            objProtecol NetCmd = (objProtecol)obj;
            if (NetCmd.Flag == 0x0f)    //数据包
            {
                byte[] sBuf = NetCmd.Data.ToArray();
                byte[] dcode = new byte[3];
                Array.Copy(sBuf, 0, dcode, 0, 3); //目的电报码
                byte[] scode = new byte[3];
                Array.Copy(sBuf, 3, scode, 0, 3); //源电报码
                string strdcode = System.Text.UTF8Encoding.UTF8.GetString(dcode);  //目的电报码
                string strscode = System.Text.UTF8Encoding.UTF8.GetString(scode);  //源电报码
                if (strdcode != c_Config.sysConfig.TelexCode) return;              //非本机的电报码
                byte cmdFlag = sBuf[6]; //命令和数据包标志
                byte rarFlag = 0;
                int m = 7;
                if (cmdFlag == 0)   //数据包有压缩标志
                {
                    rarFlag = sBuf[m++];
                }
                byte verFalg = sBuf[m++];   //版本号
                byte typeFlag = sBuf[m++];  //数据类型码
                byte dataType = sBuf[m++];  //数据子类型码
                #region 模拟量实时值
                if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x11 && dataType != 0xff) //提取一种模拟量实时值命令
                {
                    c_NetCom.RetSendOneTypeRealTimeValueData(strscode, dataType);   //发送同一种类型模拟量实时数据的回执
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x11 && dataType != 0xff)    //收到模拟量实时数据
                {
                    DisposeAnalogRealTimeValue(dataType, sBuf, m);
                }
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x11 && dataType == 0xff)    //提取特定模拟量值命令
                {
                    List<AnalogObj> li = new List<AnalogObj>();
                    int num = sBuf[m] + (sBuf[m + 1] << 8);
                    m += 2;
                    for (int i = 0; i < num; i++)
                    {
                        AnalogObj t = new AnalogObj();
                        t.type = (AnalogCodeType)sBuf[m];   //模拟量类型只取一个字节
                        m += 2;
                        t.devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        li.Add(t);
                    }
                    c_NetCom.RetSendSpecifiedAnalogRTData(strscode, li.ToArray(), num);     //发送取特定模拟量数据的回执
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x11 && dataType == 0xff)
                {
                    DisposeSpecialAnalogRealTimeValue(sBuf, m);
                }
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x12)    //发送提取模拟量最新值命令
                {
                    c_NetCom.RetSendAnalogNewstValueData(strscode, dataType);   //回执最新值命令
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x12)
                {
                    DisposeNewstRealTimeValue(dataType, sBuf, m);   //绝缘、漏流、残压
                }
                #endregion
                #region 日报表,日曲线
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x13)    //提取日报表时间和数据命令
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)  //提取时间
                    {
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(DisposeGetTimeList), ok);
                    }
                    else if (dflag == 0x41) //提取数据
                    {
                        int utime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ok.utime = utime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(DisposeGetDailyReportData), ok);
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x13)    //终端接收日报表时间列表和数据
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)  //时间回执
                    {
                        tDisposeRevDailyReportTimeList(dataType, sBuf, m);
                    }
                    else if (dflag == 0x41) //数据回执
                    {
                        tDisposeRevDailyReportData(dataType, sBuf, m);
                    }
                }
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x15)    //终端调阅日曲线
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)  //提取时间
                    {
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetDailyCurveTimeList), ok);
                    }
                    else if (dflag == 0x41) //提取数据命令
                    {
                        int devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int etime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ok.DevNo = devNo;
                        ok.stime = stime;
                        ok.etime = etime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetDailyCurveData), ok);
                    }
                    else if (dflag == 0x42) //提取回溯数据
                    {
                        int devNo = sBuf[m] + ((sBuf[m + 1] << 8));
                        m += 2;
                        int stime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int etime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int recallNum = sBuf[m] + ((sBuf[m + 1] << 8));
                        m += 2;
                        int recallstime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        int recalletime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //重复结束时间
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ok.DevNo = devNo;
                        ok.stime = stime;
                        ok.etime = etime;
                        ok.recallNum = recallNum;
                        ok.recallstime = recallstime;
                        ok.recalletime = recalletime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetDailyCurveDataRecall), ok);
                    }
                }
                #endregion
                #region  终端收到日曲线回执
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x15)    //终端收到日曲线回执
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x42)  //终端收到日曲线回溯数据
                    {
                        int rNum = sBuf[m]++;   //重复次数
                        int rstime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        int retime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        DateTime tmpTime = MySql.Time_tToDateTime(rstime);
                        if (tmpTime.Hour >= 12) //下午数据的回溯
                        {
                            TerminalDailyPmCurveRecallTime.rNum = rNum;
                            TerminalDailyPmCurveRecallTime.srecalltime = rstime;
                            TerminalDailyPmCurveRecallTime.erecalltime = retime;
                        }
                        else    //上午的回溯时间
                        {
                            TerminalDailyAmCurveRecallTime.rNum = rNum;
                            TerminalDailyAmCurveRecallTime.srecalltime = rstime;
                            TerminalDailyAmCurveRecallTime.erecalltime = retime;
                        }
                        ///在此处要弹出让用户选择哪段时间对话框。
                        MessageBox.Show("弹出用户选择框");
                    }
                    else if (dflag == 0x41)  //终端收到日曲线数据
                    {
                        int DevNo = sBuf[m] + ((sBuf[m + 1] << 8));
                        m += 2;
                        int recordNum = sBuf[m] + ((sBuf[m + 1] << 8));
                        m += 2;
                        List<objTimeValue> li = new List<objTimeValue>();
                        string typeName = c_Device.GetAnalogTypeName((AnalogCodeType)dataType);
                        int amData = 0;    //区分是上下午的数据
                        DateTime DataDay = new DateTime();
                        for (int i = 0; i < recordNum; i++)
                        {
                            objTimeValue tmp = new objTimeValue();
                            int v = sBuf[m] + ((sBuf[m + 1] << 8));
                            m += 2;
                            int t = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                            m += 4;
                            tmp.u_time = t;
                            tmp.Dvalue = (short)v;
                            tmp.Tvalue = c_RealTimeValue.ConvertAnalogValue(typeName, (short)v);    //转换成float值
                            li.Add(tmp);
                            DataDay = MySql.Time_tToDateTime(v);
                            if (amData == 0)    //0表示要区分上下午数据
                            {
                                if (DataDay.Hour >= 12) amData = 2; //2表示是下午的数据
                                else amData = 1;  //3表示是上午的数据
                            }
                        }
                        objCodeDev cd = new objCodeDev();
                        cd.codetype = dataType;
                        cd.dev_no = (short)DevNo;
                        objDate tmpDate = MySql.DateTimeToobjDate(DataDay);
                        if (tmpDate.day != TerminalDailyCurveDay.day || tmpDate.month != TerminalDailyCurveDay.month || tmpDate.year != TerminalDailyCurveDay.year)
                        {
                            TerminalDailyCurveDay = tmpDate;
                            TermianlAmDailyCurveValueList.Clear();
                            TermianlPmDailyCurveValueList.Clear();
                            TerminalDailyAmCurveRecallTime.rNum = 0;
                            TerminalDailyPmCurveRecallTime.rNum = 0;
                        }

                        if (amData == 1)
                        {
                            if (TermianlAmDailyCurveValueList.Keys.Contains(cd)) TermianlAmDailyCurveValueList.Remove(cd);
                            TermianlAmDailyCurveValueList.Add(cd, li);
                        }
                        else if (amData == 2)
                        {
                            if (TermianlPmDailyCurveValueList.Keys.Contains(cd)) TermianlPmDailyCurveValueList.Remove(cd);
                            TermianlPmDailyCurveValueList.Add(cd, li);
                        }
                    }
                }
                #endregion
                #region 站机处理终端调取高频模拟量命令
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x30)
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x41)  //提取高频曲线
                    {
                        int devNo = sBuf[m] + ((sBuf[m + 1] << 8));
                        m += 2;
                        int stime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                        m += 4;
                        int etime = sBuf[m] + ((sBuf[m + 1] << 8)) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //结束时间
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ok.DevNo = devNo;
                        ok.stime = stime;
                        ok.etime = etime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetDailyHigFrequencyData), ok);
                    }
                    else if (dflag == 0x42) //提取回溯段时间数据
                    {
                        int devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //结束时间
                        m += 4;
                        int recallNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int recallstime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        int recalletime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //重复结束时间
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ok.DevNo = devNo;
                        ok.stime = stime;
                        ok.etime = etime;
                        ok.recallNum = recallNum;
                        ok.recallstime = recallstime;
                        ok.recalletime = recalletime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetHigFrequencyDataRecall), ok);
                    }
                }
                #endregion
                #region 终端接收高频模拟量回执
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x30)
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x42)  //终端收到高频日曲线回溯数据
                    {
                        int rNum = sBuf[m]++;   //重复次数
                        int rstime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        int retime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        DateTime tmpTime = MySql.Time_tToDateTime(rstime);
                        if (tmpTime.Hour >= 12) //下午数据的回溯
                        {
                            TerminalDailyPmHigCurveRecallTime.rNum = rNum;
                            TerminalDailyPmHigCurveRecallTime.srecalltime = rstime;
                            TerminalDailyPmHigCurveRecallTime.erecalltime = retime;
                        }
                        else    //上午的回溯时间
                        {
                            TerminalDailyAmHigCurveRecallTime.rNum = rNum;
                            TerminalDailyAmHigCurveRecallTime.srecalltime = rstime;
                            TerminalDailyAmHigCurveRecallTime.erecalltime = retime;
                        }
                        ///在此处要弹出让用户选择哪段时间对话框。
                        MessageBox.Show("弹出用户选择框");
                    }
                    else if (dflag == 0x41)  //终端收到日曲线数据
                    {
                        int freq = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int DevNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int recordNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        List<HigFreAnalogValue> li = new List<HigFreAnalogValue>();
                        string typeName = c_Device.GetAnalogTypeName((AnalogCodeType)dataType);
                        int amData = 0;    //区分是上下午的数据
                        DateTime DataDay = new DateTime();

                        for (int i = 0; i < recordNum; i++)
                        {
                            HigFreAnalogValue tmp = new HigFreAnalogValue();
                            for (int j = 0; j < freq; j++)
                            {
                                int v = sBuf[m] + (sBuf[m + 1] << 8);
                                m += 2;
                                int t = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                                m += 4;
                                tmp.utime = t;
                                objHigFre tmpsecond = new objHigFre();
                                tmpsecond.wValue = (short)v;
                                tmpsecond.fValue = c_RealTimeValue.ConvertAnalogValue(typeName, (short)v);    //转换成float值
                                tmp.SecondValueList.Add(tmpsecond);
                            }
                            li.Add(tmp);
                            DataDay = MySql.Time_tToDateTime(tmp.utime);
                            if (amData == 0)    //0表示要区分上下午数据
                            {
                                if (DataDay.Hour >= 12) amData = 2; //2表示是下午的数据
                                else amData = 1;  //3表示是上午的数据
                            }
                        }
                        objCodeDev cd = new objCodeDev();
                        cd.codetype = dataType;
                        cd.dev_no = (short)DevNo;
                        objDate tmpDate = MySql.DateTimeToobjDate(DataDay);
                        if (tmpDate.day != TerminalDailyHigCurveDay.day || tmpDate.month != TerminalDailyHigCurveDay.month || tmpDate.year != TerminalDailyHigCurveDay.year)
                        {
                            TerminalDailyHigCurveDay = tmpDate;
                            TermianlPmDailyHigCurveValueList.Clear();
                            TermianlAmDailyHigCurveValueList.Clear();
                            TerminalDailyAmHigCurveRecallTime.rNum = 0;
                            TerminalDailyPmHigCurveRecallTime.rNum = 0;
                        }

                        if (amData == 1)
                        {
                            if (TermianlAmDailyHigCurveValueList.Keys.Contains(cd)) TermianlAmDailyHigCurveValueList.Remove(cd);
                            TermianlAmDailyHigCurveValueList.Add(cd, li);
                        }
                        else if (amData == 2)
                        {
                            if (TermianlPmDailyHigCurveValueList.Keys.Contains(cd)) TermianlPmDailyHigCurveValueList.Remove(cd);
                            TermianlPmDailyHigCurveValueList.Add(cd, li);
                        }
                    }
                }
                #endregion
                #region 开关量回放
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x16 && dataType == 0xff)
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)      //提取开关量时间列表
                    {
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(DisposeGetKglTimeList), ok);
                    }
                    else if (dflag == 0x41) //提取开关量数据
                    {
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //结束时间
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ok.stime = stime;
                        ok.etime = etime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(DisposeGetKglReplayData), ok);
                    }
                    else if (dflag == 0x42)
                    {
                        int devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //结束时间
                        m += 4;
                        int recallNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int recallstime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        int recalletime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //重复结束时间
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = dataType;
                        ok.DevNo = devNo;
                        ok.stime = stime;
                        ok.etime = etime;
                        ok.recallNum = recallNum;
                        ok.recallstime = recallstime;
                        ok.recalletime = recalletime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetkglDataRecall), ok);
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x16 && dataType == 0xff)    //终端收到开关量回执数据
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)      //返回开关量时间列表
                    {
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //结束时间
                        m += 4;
                        KGLReplayStime = stime;
                        KGLReplayEtime = etime;
                    }
                    else if (dflag == 0x42 && sBuf.Length < 30) //返回开关量回溯时间,跟回溯的数据命令一致
                    {
                        KGLRecallRum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        KGLRecallStime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        KGLRecallEtime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //重复结束时间
                        m += 4;
                        MessageBox.Show("开关量回溯时间选择");
                    }
                    else if ((dflag == 0x41 || dflag == 0x42) && sBuf.Length >= 30)
                    {
                        TerminalReplayAnalogValue.Clear();
                        Array.Copy(sBuf, m - 1, TerminalReplayAnalogValue.ToArray(), 0, sBuf.Length - 11);
                        tDisposeRevKglReplayData();
                    }
                }
                #endregion
                #region 模拟量回放
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x16 && dataType == 0xf0)
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x41)  //模拟量回放数据
                    {
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int AnalogNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        List<byte> AnalogSet = new List<byte>();
                        if (AnalogNum != 0xff)
                        {
                            for (int i = 0; i < AnalogNum; i++)
                            {
                                AnalogSet.Add(sBuf[m++]);
                            }
                        }
                        objNetAnalogReplay ok = new objNetAnalogReplay();
                        ok.sCode = strscode;
                        ok.stime = stime;
                        ok.etime = etime;
                        ok.analogNum = AnalogNum;
                        ok.AnalogSet = AnalogSet;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetAnalogData), ok);
                    }
                    else if (dflag == 0x42) //模拟量回溯时间段数据
                    {
                        int devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //结束时间
                        m += 4;
                        int recallNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int recallstime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        int recalletime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //重复结束时间
                        m += 4;
                        objNetAnalogReplay ok = new objNetAnalogReplay();
                        ok.sCode = strscode;
                        ok.stime = stime;
                        ok.etime = etime;
                        ok.recalletime = recalletime;
                        ok.recallNum = recallNum;
                        ok.recallstime = recallstime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetAnalogRecallData), ok);
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x16 && dataType == 0xf0)
                {
                    byte dflag = sBuf[m++];
                    int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                    m += 4;
                    int rarSize = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //压缩包长度
                    m += 4;
                    byte[] rarBuf = new byte[rarSize];
                    Array.Copy(sBuf, m, rarBuf, 0, rarSize);
                    byte[] unRarBuf = new byte[1024 * 1024 * 5];   //5M缓冲区
                    int unRarSize = 1024 * 1024 * 5;
                    c_NetCom.zUNcompress(rarBuf, rarSize, unRarBuf, ref unRarSize, 0); //解压缩
                    TerminalReplayAnalogValue.Clear();
                    for (int i = 0; i < unRarSize; i++)
                    {
                        TerminalReplayAnalogValue.Add(unRarBuf[i]);     //模拟量数据装入缓冲区
                    }
                    TerminalDisposeReplayAnalogValue(dflag, stime);
                }
                #endregion
                #region 高频模拟量回放
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x31 && dataType == 0xf0)
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x41)  //模拟量回放数据
                    {
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int AnalogNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        List<byte> AnalogSet = new List<byte>();
                        if (AnalogNum != 0xff)
                        {
                            for (int i = 0; i < AnalogNum; i++)
                            {
                                AnalogSet.Add(sBuf[m++]);
                            }
                        }
                        objNetAnalogReplay ok = new objNetAnalogReplay();
                        ok.sCode = strscode;
                        ok.stime = stime;
                        ok.etime = etime;
                        ok.analogNum = AnalogNum;
                        ok.AnalogSet = AnalogSet;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetHighFrequencyReplayData), ok);
                    }
                    else if (dflag == 0x42) //模拟量回溯时间段数据
                    {
                        int devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //结束时间
                        m += 4;
                        int recallNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int recallstime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //重复开始时间
                        m += 4;
                        int recalletime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);   //重复结束时间
                        m += 4;
                        objNetAnalogReplay ok = new objNetAnalogReplay();
                        ok.sCode = strscode;
                        ok.stime = stime;
                        ok.etime = etime;
                        ok.recalletime = recalletime;
                        ok.recallNum = recallNum;
                        ok.recallstime = recallstime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetHighFrequencyReplayRecallData), ok);
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x16 && dataType == 0xf0)
                {
                    byte dflag = sBuf[m++];
                    int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //开始时间
                    m += 4;
                    int rarSize = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);  //压缩包长度
                    m += 4;
                    byte[] rarBuf = new byte[rarSize];
                    Array.Copy(sBuf, m, rarBuf, 0, rarSize);
                    byte[] unRarBuf = new byte[1024 * 1024 * 5];   //5M大缓存
                    int unRarSize = 1024 * 1024 * 5;
                    c_NetCom.zUNcompress(rarBuf, rarSize, unRarBuf, ref unRarSize, 0); //解压缩
                    TerminalReplayHighFrequencyValue.Clear();
                    for (int i = 0; i < unRarSize; i++)
                    {
                        TerminalReplayHighFrequencyValue.Add(unRarBuf[i]);     //模拟量数据装入缓冲区
                    }
                    TerminalDisposeReplayHighFrequencyValue(dflag, stime);
                }
                #endregion
                #region 开关量
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x17 && dataType == 0x80)   //实时全体开关量数据
                {
                    objRevKGL t = new objRevKGL();
                    t.AllFlag = true;
                    t.kglNum = sBuf[m] + (sBuf[m + 1] << 8);
                    m += 2;
                    t.time = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                    m += 4;
                    int Length = sBuf[m] + (sBuf[m + 1] << 8);             //开关量数据总长度      
                    m += 2;
                    for (int i = 0; i < Length; i++)
                    {
                        t.Value.Add(sBuf[m + i]);
                    }
                    m += Length;
                    int tick = sBuf[m] + (sBuf[m + 1] << 8);
                    m += 2;

                    if (tick == RevKglTick) //包序号正确
                    {
                        c_RealTimeValue.ReceiveKGLData = t;     //丢入到实时数据缓冲区
                        RevKglTick = tick + 1;
                    }
                    else if (RevKglTick == tick + 1) //包序号和上包相同，非法数据
                    {
                        //非法数据
                        c_NetCom.AutoSendKGLALLRealTimeData();
                    }
                    else if (RevKglTick < tick)//数据重新开始了                  
                    {
                        c_RealTimeValue.ReceiveKGLData = t;
                        RevKglTick = tick + 1;
                    }
                    else //中间丢了数据
                    {
                        c_RealTimeValue.ReceiveKGLData = t;
                        RevKglTick = tick + 1;
                        c_NetCom.AutoSendKGLALLRealTimeData();
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x17 && dataType == 0x81)        //实时变化开关量数据
                {
                    objRevKGL t = new objRevKGL();
                    t.AllFlag = true;
                    t.kglNum = sBuf[m] + (sBuf[m + 1] << 8);
                    m += 2;
                    t.time = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                    m += 4;
                    int Length = sBuf[m] + (sBuf[m + 1] << 8);             //开关量数据总长度      
                    m += 2;
                    for (int i = 0; i < Length; i++)
                    {
                        t.Value.Add(sBuf[m + i]);
                    }
                    m += Length;
                    int tick = sBuf[m] + (sBuf[m + 1] << 8);
                    m += 2;

                    if (tick == RevKglTick) //包序号正确
                    {
                        c_RealTimeValue.ReceiveChangeKglData = t;
                        RevKglTick = tick + 1;
                    }
                    else if (RevKglTick == tick + 1) //包序号和上包相同，非法数据
                    {
                        //非法数据
                        c_NetCom.AutoSendKGLALLRealTimeData();
                    }
                    else if (RevKglTick < tick)//数据重新开始了                  
                    {
                        c_RealTimeValue.ReceiveChangeKglData = t;
                        RevKglTick = tick + 1;
                    }
                    else //中间丢了数据
                    {
                        c_RealTimeValue.ReceiveChangeKglData = t;
                        RevKglTick = tick + 1;
                        c_NetCom.AutoSendKGLALLRealTimeData();
                    }
                    c_RealTimeValue.DisposeChangeKgl(t);
                }
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x17 && dataType == 0x80) //请求全体实时开关量信息
                {
                    c_NetCom.AutoSendKGLALLRealTimeData();
                }
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x17 && dataType == 0x82)  //请求开关量历史数据
                {
                    int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                    m += 3;
                    int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                    m += 3;
                    objNetCode ok = new objNetCode();
                    ok.sCode = strscode;
                    ok.type = dataType;
                    ok.stime = stime;
                    ok.etime = etime;
                    ThreadPool.QueueUserWorkItem(new WaitCallback(DisposeGetKglHistoryData), ok);
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x17 && dataType == 0x82)  //站机回执开关量历史数据
                {
                    TerminalHistoryKglValue.Clear();
                    Array.Copy(sBuf, m, TerminalHistoryKglValue.ToArray(), 0, sBuf.Length - 11);
                    tDisposeRevKglHistoryData();
                }
                #endregion
                #region 记录曲线
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x18)    //提取记录曲线
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)
                    {
                        int devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.sontype = dataType;
                        ok.DevNo = devNo;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetRecordCurveTimeList), ok);
                    }
                    else if (dflag == 41)
                    {
                        int devNo = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.sontype = dataType;
                        ok.DevNo = devNo;
                        ok.stime = stime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetRecordCurveValueList), ok);
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x18)    //提取记录曲线
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)  //时间列表
                    {
                        int rNum = sBuf[m] + (sBuf[m + 1] << 8);  //记录数
                        m += 2;
                        for (int i = 0; i < rNum; i++)
                        {
                            int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                            m += 4;
                            TerminalRecordCurveTimeList.Add(MySql.Time_tToDateTime(stime));
                        }
                    }
                    else if (dflag == 0x41) //曲线内容
                    {
                        DisposeRecordCurveData(dataType, sBuf, m);
                    }
                }
                #endregion
                #region 空调
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x33)
                {
                    if (dataType == 0x01)   //查询空调参数
                    { }
                    else if (dataType == 0x03) //修改空调状态及参数
                    { }
                    else if (dataType == 0x05)  //控制空调
                    { }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x33)
                {
                    if (dataType == 0x02)   //查询空调参数 回执
                    { }
                    else if (dataType == 0x04) //修改空调状态及参数 回执
                    { }
                    else if (dataType == 0x06)  //控制空调 回执
                    { }
                }
                #endregion
                #region 统计
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x19)
                {
                    int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                    objNetCode ok = new objNetCode();
                    ok.sCode = strscode;
                    ok.sontype = dataType;
                    ok.stime = stime;
                    ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetTongJiData), ok);
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x19)
                {
                    DisposeTongJiData(dataType, sBuf, m);
                }
                #endregion
                #region 实时、历史报警
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x1a) //终端处理接收到的实时报警数据
                {
                    DisposeRealTimeAlarmData(verFalg, dataType, sBuf, m);
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe2 && typeFlag == 0x1a) //站机处理服务器返回的实时报警回执
                {
                    DisposeRealTimeAlarmData(verFalg, dataType, sBuf, m);
                }
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x1a)    //站机处理报警数据命令
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)      //时间
                    {
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.sontype = dataType;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetAlaramTimeList), ok);
                    }
                    else if (dflag == 0x42)  //数据
                    {
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m += 4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.sontype = dataType;
                        ok.stime = stime;
                        ok.etime = etime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDisposeGetAlaramValueList), ok);
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x1a)    //终端处理历史报警
                {
                    byte dflag = sBuf[m++];
                    if (dflag == 0x40)      //报警时间
                    {
                        int rNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        List<DateTime> li = new List<DateTime>();
                        for (int i = 0; i < rNum; i++)
                        {
                            int utime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                            m += 4;
                            DateTime d = MySql.Time_tToDateTime(utime);
                            li.Add(d);
                        }
                        if (TerminalAlarmTimeList.ContainsKey(dataType)) TerminalAlarmTimeList.Remove(dataType);
                        TerminalAlarmTimeList.Add(dataType, li);
                    }
                    else if (dflag == 0x42) //报警数据
                    {
                        DisposeHistoryAlarmData(dataType, sBuf, m);
                    }
                }
                #endregion
                #region 列控
                else if (cmdFlag == 0x01 && verFalg == 0xe0 && typeFlag == 0x51)
                {
                    int lkNo = dataType;        //列控个数编号
                    byte dflag = sBuf[m++];
                    if (dflag == 0x01)      //获取实时命令
                    {
                        byte protecol = sBuf[m++];
                        zDiaposelkRealTimeValue(strscode, lkNo, protecol);
                    }
                    else if (dflag == 0x40)    //获取列控时间列表
                    {
                        byte protecol = sBuf[m++];
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = protecol;
                        ok.DevNo = lkNo;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDiaposelkTimeList),ok);                             
                    }
                    else if (dflag == 0x41) //获取列控历史数据
                    {
                        byte protecol = sBuf[m++];
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m+=4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m+=4;
                        objNetCode ok = new objNetCode();
                        ok.sCode = strscode;
                        ok.type = protecol;
                        ok.DevNo = lkNo;
                        ok.stime = stime;
                        ok.etime = etime;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(zDiaposelkHistoryData), ok);
                    }
                }
                else if (cmdFlag == 0x00 && verFalg == 0xe0 && typeFlag == 0x51)
                {
                    int lkNo = dataType;        //列控个数编号
                    byte dflag = sBuf[m++];
                    if (dflag == 0x01)      //实时数据回执
                    {
                        tDisposeRevLkRealTimeValue(sBuf,m);
                    }
                    else if (dflag == 0x40) //列控时间列表回执
                    {
                        int protecol = sBuf[m++];
                        int stime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m+=4;
                        int etime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
                        m+=4;
                        TerminalLkHistoryStartTime = MySql.Time_tToDateTime(stime);
                        TerminalLkHistoryEndTime = MySql.Time_tToDateTime(etime);
                    }
                    else if (dflag == 0x41) //列控历史信息回执
                    {
                        tDisposeRevLkHistroyValue(sBuf, m);
                    }
                }
                #endregion
            }
        }
        private static void tDisposeRevLkHistroyValue(byte[] sbuf, int offset)
        {
            int m = offset;
            int type = sbuf[m++];
            int stime = sbuf[m] + (sbuf[m + 1] << 8) + (sbuf[m + 2] << 16) + (sbuf[m + 3] << 24);
            m += 4;
            int rnum = sbuf[m] + (sbuf[m + 1] << 8);    //记录数
            m += 2;
            if (sbuf[sbuf.Length - 1] != 0xff)   //最后一个字节为0xff
            {
                Console.WriteLine("列控历史数据回执错误");
                return;
            }
            byte[] pr = new byte[sbuf.Length-m-1];  //解压前数据
            Array.Copy(sbuf, m, pr, 0, (sbuf.Length - m - 1));
            byte[] un = new byte[pr.Length * 20];
            int unLength = un.Length;
            c_NetCom.zUNcompress(pr, pr.Length, un, ref unLength, 1);
            m = 0;
            if (type == 0x01 || type == 0x02)   //硬件平台
            {
                if (type == 0x01)HostHardwarePlatform_ASet.Clear();                
                else HostHardwarePlatform_BSet.Clear();                
                for (int i = 0; i < rnum; i++)
                {                    
                    int dtime = un[m] + (un[m + 1] >> 8) + (un[m + 2] >> 16) + (un[m + 3] >> 24);
                    m += 4;
                    string strTime = MySql.Time_tToDateTime(dtime).ToString();
                    DataTable dt = new DataTable(strTime);
                    c_LK.InitHostHardwarePlatform(ref dt);
                    dt.Rows[0]["状态"] = strTime;   //第1行固定时间
                    int ls = un[m] + (un[m + 1] >> 8);  //总路数
                    m += 2;
                    int hs = ls;  //实际填充的行数
                    if (ls > (dt.Rows.Count-1)) hs = (dt.Rows.Count-1);     //实际的行数比配置多一行时间
                    for (int k = 0; k < ls; k++)
                    {
                        int txtlen = un[m] + (un[m + 1] >> 8); //明文长度
                        m += 2;
                        byte[] txt = new byte[txtlen];
                        Array.Copy(un, m, txt, 0, txtlen);
                        string s = System.Text.Encoding.Default.GetString(txt);
                        if (k < hs) //只填充配置的行数
                        {
                            dt.Rows[k + 1]["状态"] = s;
                        }
                    }
                    if (type == 0x01) HostHardwarePlatform_ASet.Tables.Add(dt);
                    else HostHardwarePlatform_BSet.Tables.Add(dt);                
                }
            }
            else if (type == 0x11)  //轨道区段编码信息
            {
                SectionEncodeInfo.Clear();
                for (int i = 0; i < rnum; i++)
                {
                    int dtime = un[m] + (un[m + 1] >> 8) + (un[m + 2] >> 16) + (un[m + 3] >> 24);
                    m += 4;
                    string strTime = MySql.Time_tToDateTime(dtime).ToString();
                    DataTable dt = new DataTable(strTime);
                    c_LK.InitSectionEncodeInfo(ref dt);
                    int ls = un[m] + (un[m + 1] >> 8);  //总路数
                    m += 2;
                    int hs = ls;  //实际填充的行数
                    if (ls > (dt.Rows.Count)) hs = dt.Rows.Count;
                    for (int k = 0; k < ls; k++)
                    {
                        int txtlen = un[m] + (un[m + 1] >> 8); //明文长度
                        m += 2;
                        byte[] txt = new byte[txtlen];
                        Array.Copy(un, m, txt, 0, txtlen);
                        string s = System.Text.Encoding.Default.GetString(txt);
                        string[] sb = s.Split('@');
                        if (sb.Length != 4)
                        {
                            Console.WriteLine("终端接收列控历史数据错误");
                            return;
                        }
                        if (k < dt.Rows.Count)
                        {
                            dt.Rows[k]["主轨载频编码"] = sb[0];
                            dt.Rows[k]["小轨载频编码"] = sb[1];
                            dt.Rows[k]["主轨低频编码"] = sb[2];
                            dt.Rows[k]["小轨低频编码"] = sb[3];
                        }
                    }
                    SectionEncodeInfo.Tables.Add(dt);
                }
            }
            else if ((type >= 0x03 && type <= 0x09) || (type >= 0x10 && type <= 0x12))
            {
                DataTable dt = new DataTable();
                if (type == 0x03) dt = LianSuoJieKouRouteInfo;
                else if (type == 0x04) dt = LianSuoGaiFangCommandInfo;
                else if (type == 0x05) dt = LianSuoGaiFangCommandRet;
                else if (type == 0x06) dt = ZhanJianGaiFangCommandInfo;
                else if (type == 0x07) dt = ZhanJianGaiFangCommandRet;
                else if (type == 0x08) dt = ZhanJianBoundaryInfo;
                else if (type == 0x09) dt = SendToLianSuoInfo;
                else if (type == 0x10) dt = TemporaryLimitSpeedState;
                else if (type == 0x12) dt = TransponderEncodeInfo;
                dt.Rows.Clear();
                for (int i = 0; i < rnum; i++)
                {
                    int dtime = un[m] + (un[m + 1] >> 8) + (un[m + 2] >> 16) + (un[m + 3] >> 24);
                    m += 4;
                    int ls = un[m] + (un[m + 1] >> 8);  //总路数
                    m += 4;
                    for (int k = 0; k < ls; k++)
                    {
                        int txtlen = un[m] + (un[m + 1] >> 8); //明文长度
                        m += 2;
                        byte[] txt = new byte[txtlen];
                        Array.Copy(un, m, txt, 0, txtlen);
                        string s = System.Text.Encoding.Default.GetString(txt);
                        string[] sb = s.Split('@');
                        int ik = 0;  //需要插入的列数
                        if (sb.Length >= (dt.Columns.Count - 1)) ik = dt.Columns.Count - 1;
                        else ik = sb.Length;
                        DataRow dr = dt.NewRow();
                        for (int x = 1; x <= ik; x++)
                        {
                            dr[x] = sb[x - 1];
                        }
                        dt.Rows.Add(dr);
                    }
                }
            }
        }
        private static void tDisposeRevLkRealTimeValue(byte[] sBuf, int offset)
        {
            List<byte> li = new List<byte>();
            Array.Copy(sBuf, offset, li.ToArray(), 0, sBuf.Length - offset);
            NewLKEvent(li, new EventArgs());
        }
        /// <summary>
        /// 历史报警加入缓冲区
        /// </summary>
        /// <param name="AlarmType"></param>
        /// <param name="obj"></param>
        private static void AddToHistoryAlarmData(byte AlarmType,ObjAlaram obj)
        {
            objHistoryAlaramKey key = new objHistoryAlaramKey();
            key.date = MySql.Time_tToObjDate(obj.u_time);
            key.AlarmType = AlarmType;
            if (TerminalAlarmValueList.Keys.Contains(key))
            {
                TerminalAlarmValueList[key].Add(obj);
            }
            else
            {
                List<ObjAlaram> li = new List<ObjAlaram>();
                li.Add(obj);
                TerminalAlarmValueList.Add(key, li);
            }
        }
        /// <summary>
        /// 终端处理收到的历史数据
        /// </summary>
        /// <param name="CurveType"></param>
        /// <param name="sBuf"></param>
        /// <param name="offset"></param>
        private static void DisposeHistoryAlarmData(byte CurveType, byte[] sBuf, int offset)
        {
            int m = offset;
            
            List<ObjAlaram> ali = new List<ObjAlaram>();

            if(CurveType == 0x06)
            {
                ali = MySql.byteBufToObjAlarmList(sBuf,m,1,1);
            }
            else
            {
                ali = MySql.byteBufToObjAlarmList(sBuf,m,1,0);
            }
            for(int i = 0;i<ali.Count;i++)
            {
                AddToHistoryAlarmData(CurveType, ali[i]);
            }
        }
        
        /// <summary>
        /// 站机 终端处理实时报警信息
        /// </summary>
        /// <param name="CurveType"></param>
        /// <param name="sBuf"></param>
        /// <param name="offset"></param>
        private static void DisposeRealTimeAlarmData(int verFalg, byte CurveType, byte[] sBuf, int offset)
        {
            int m = offset;            
            m++;                //0x00,
            List<ObjAlaram> li = MySql.byteBufToObjAlarmList(sBuf, m, 0, 0);

            if (li.Count == 1)
            {
                ObjAlaram obj = li[0];
                obj.AlarmType = CurveType;
                if (verFalg == 0xe0)    //终端收到服务器转发的数据
                {
                    NewAlarmEvent(obj, new EventArgs());                    
                }
                else if (verFalg == 0xe2)   //站机收到服务器回执,要删除等待回执的数据
                {
                    EventRevSevAlarmRet(obj, new EventArgs());                          
                }
            }
        }
        private static void AddToTerminalTongJi(objTongJiKey key, objTongJiReport otj)
        {
            if (TerminalTongJiValueList.Keys.Contains(key))
            {
                bool f = false;
                foreach (objTongJiReport s in TerminalTongJiValueList[key])
                {
                    if (s.year == otj.year && s.month == otj.month)
                    {
                        f = true;
                        break;
                    }
                }
                if (f == false)
                {
                    TerminalTongJiValueList[key].Add(otj);
                }
            }
            else
            {
                List<objTongJiReport> k = new List<objTongJiReport>();
                k.Add(otj);
                TerminalTongJiValueList.Add(key, k);
            }
        }
        /// <summary>
        /// 终端处理接收到的统计数据
        /// </summary>
        /// <param name="CurveType"></param>
        /// <param name="sBuf"></param>
        /// <param name="offset"></param>
        private static void DisposeTongJiData(byte CurveType, byte[] sBuf, int offset)
        {
            int m = offset;
            int rNum = sBuf[m] + (sBuf[m + 1] << 8);  //记录数
            m += 2;
            int time = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24); //时间
            m += 4;
            DateTime tm = MySql.Time_tToDateTime(time);
            objTongJiKey okey = new objTongJiKey();
            okey.type = CurveType;

            for (int i = 0; i < rNum; i++)
            {
                objTongJiReport otj = new objTongJiReport();
                otj.year = tm.Year;
                otj.month = tm.Month;
                otj.totolTime = (short)(sBuf[m] + (sBuf[m + 1] << 8));    //累计时间；
                m += 2;
                int DevNo = sBuf[m] + (sBuf[m + 1] << 8);         //设备序号；
                m += 2;
                okey.DevName = c_Device.GetTongJiDevName(CurveType, DevNo);
                otj.totalCount = (short)(sBuf[m] + (sBuf[m + 1] << 8));   //累计次数
                m += 2;
                AddToTerminalTongJi(okey, otj);
            }
        }
                
        /// <summary>
        /// 终端处理记录曲线命令
        /// </summary>
        /// <param name="CurveType"></param>
        /// <param name="sBuf"></param>
        /// <param name="offset"></param>
        private static void DisposeRecordCurveData(byte CurveType, byte[] sBuf, int offset)
        {
            int m = offset;
            int rNum = sBuf[m] + (sBuf[m + 1] << 8);  //记录数
            m += 2;
            if (CurveType == 0x10)   //道岔动作电流曲线
            {
                objRecordCurveKey key = new objRecordCurveKey();
                ObjDcdlType obj = new ObjDcdlType();
                int xiangwei = -1;
                for (int i = 0; i < rNum; i++)
                {                    
                    byte ctype = sBuf[m++];
                    int devNo = sBuf[m] + (sBuf[m + 1] << 8); //道岔内序号
                    if (xiangwei == -1)
                    {
                        int switchType = c_Device.GetDctype(devNo); //道岔类型，确定是否有三相
                        if (switchType == 1) xiangwei = 1;      //表示有三相，为0时只有1相
                    }
                    m += 2;
                    int time = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24); //时间
                    m += 4;
                    if (xiangwei == 0 || xiangwei == 1)
                    {
                        key.time = MySql.Time_tToDateTime(time);
                        key.DevType = CurveType;
                        key.DevNo = devNo;
                    }
                    byte order = sBuf[m++]; //转换方向
                    int dotNum = sBuf[m] + (sBuf[m + 1] << 8);    //测试点数
                    m += 2;
                    if (xiangwei == 0 || xiangwei == 1)
                    {
                        obj.devNo = devNo;
                        obj.dotNumber = (short)dotNum;
                        obj.u_time = time;
                        obj.zh_order = order;
                    }
                    for (int j = 0; j < dotNum; j++)
                    {
                        ObjRCurValue v = new ObjRCurValue();
                        v.wValue = (short)(sBuf[m] + (sBuf[m + 1] << 8));
                        m += 2;
                        v.tValue = c_RealTimeValue.ConvertAnalogValue("道岔电流曲线", v.wValue);
                        if (ctype == 0)     //电流曲线
                        {
                            if (xiangwei == 0)
                            { 
                                obj.qxA.Add(v);   //只有一条电流曲线，也没有功率曲线
                                TerminalDcdlqxValueList.Add(key, obj);
                                xiangwei = -1;
                                key = new objRecordCurveKey();      //重新开辟空间，电流曲线接收完成
                                obj = new ObjDcdlType();
                            }
                            else if (xiangwei == 1)
                            {
                                obj.qxA.Add(v);
                                xiangwei++;
                            }
                            else if (xiangwei == 2)
                            {
                                obj.qxB.Add(v);
                                xiangwei++;
                            }
                            else if (xiangwei == 3)
                            {
                                obj.qxC.Add(v);
                            }
                        }
                        else if (ctype==1)     //摩擦曲线
                        {
                            if (xiangwei == 0)
                            {
                                obj.qxA.Add(v);
                                TerminalDcdzMcqxValueList.Add(key, obj);
                                xiangwei = -1;
                                key = new objRecordCurveKey();      //重新开辟空间，摩擦曲线接收完成
                                obj = new ObjDcdlType();
                            }
                            else if (xiangwei == 1)
                            {
                                obj.qxA.Add(v);
                                xiangwei++;
                            }
                            else if (xiangwei == 2)
                            {
                                obj.qxB.Add(v);
                                xiangwei++;
                            }
                            else if (xiangwei == 3)
                            {
                                obj.qxC.Add(v);
                            }
                        }
                        else if (ctype == 2)     //参考曲线
                        {
                            if (xiangwei == 0)
                            {
                                obj.qxA.Add(v);
                                TerminalDcdzCKqxValueList.Add(key, obj);
                                xiangwei = -1;
                                key = new objRecordCurveKey();      //重新开辟空间，参考曲线接收完成
                                obj = new ObjDcdlType();
                            }
                            else if (xiangwei == 1)
                            {
                                obj.qxA.Add(v);
                                xiangwei++;
                            }
                            else if (xiangwei == 2)
                            {
                                obj.qxB.Add(v);
                                xiangwei++;
                            }
                            else if (xiangwei == 3)
                            {
                                obj.qxC.Add(v);
                            }
                        }
                        else if (ctype == 3)
                        {
                            obj.glqx.Add(v);
                            TerminalDcdzMcqxValueList.Add(key, obj);
                            xiangwei = -1;
                            key = new objRecordCurveKey();      //重新开辟空间，电流曲线接收完成
                            obj = new ObjDcdlType();
                        }
                        else if (ctype == 4)
                        {
                            obj.glqx.Add(v);
                            TerminalDcdzMcqxValueList.Add(key, obj);
                            xiangwei = -1;
                            key = new objRecordCurveKey();      //重新开辟空间，摩擦曲线接收完成
                            obj = new ObjDcdlType();
                        }
                        else if (ctype == 5)
                        {
                            obj.glqx.Add(v);
                            TerminalDcdzCKqxValueList.Add(key, obj);
                            xiangwei = -1;
                            key = new objRecordCurveKey();      //重新开辟空间，摩擦曲线接收完成
                            obj = new ObjDcdlType();
                        }
                    }                    
                }
            }
            else if (CurveType == 0x13) //高压不对称曲线
            {
                objRecordCurveKey key = new objRecordCurveKey();
                ObjGybdcType obj = new ObjGybdcType();
                for (int i = 0; i < rNum; i++)
                {
                    int devNo = sBuf[m] + (sBuf[m + 1] << 8); //序号                    
                    m += 2;
                    int time = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24); //时间
                    m += 4;
                    key.time = MySql.Time_tToDateTime(time);
                    key.DevType = CurveType;
                    key.DevNo = devNo;
                    int csFre = sBuf[m] + (sBuf[m + 1] << 8);  //测试频率
                    m += 2;
                    int qxNum = sBuf[m] + (sBuf[m + 1] << 8);  //曲线条数
                    m += 2;
                    for (int j = 0; j < qxNum; j++)
                    {
                        int start = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        int dotNum = sBuf[m] + (sBuf[m + 1] << 8);
                        m += 2;
                        if (j == 0)
                        {
                            obj.start1 = start;
                            obj.dotnum1 = (short)dotNum;
                        }
                        else if (j == 1)
                        {
                            obj.start2 = start;
                            obj.dotnum2 = (short)dotNum;
                        }
                        else if (j == 2)
                        {
                            obj.start3 = start;
                            obj.dotnum3 = (short)dotNum;
                        }
                        for (int x = 0; x < dotNum; x++)
                        {
                            ObjRCurValue t = new ObjRCurValue();
                            int value = sBuf[m] + (sBuf[m + 1] << 8);
                            m += 2;
                            t.wValue = (short)value;
                            t.tValue = c_RealTimeValue.ConvertAnalogValue("高压不对称波形", (short)value);
                            if (j == 0) obj.qx1.Add(t);
                            else if (j == 1) obj.qx2.Add(t);
                            else if (j == 2) obj.qx3.Add(t);
                        }
                    }
                    TerminalGybdcValueList.Add(key, obj);
                }
            }
        }
        /// <summary>
        /// 处理接收到的模拟量实时值
        /// </summary>
        /// <param name="sBuf"></param> 传入的数据缓冲区
        /// <param name="offset"></param> 有效数据的下标值
        private static void DisposeAnalogRealTimeValue(byte type, byte[] sBuf, int offset)
        {            
            List<Int16> li = new List<short>();
            int m = offset;
            int rNum = sBuf[m] + (sBuf[m + 1] << 8);  //记录数
            m += 2;
            int utime = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24); //测量时间
            m += 4;
            for (int i = 0; i < rNum; i++)
            {
                int v = sBuf[m] + (sBuf[m + 1] << 8);
                li.Add((Int16)v);
                m += 2;
            }
            if (c_RealTimeValue.ReceiveAnalogData.ContainsKey(type)) c_RealTimeValue.ReceiveAnalogData.Remove(type);
            c_RealTimeValue.ReceiveAnalogData.Add(type, li);    //加入到实时值缓冲区内.
            c_RealTimeValue.DisposeAnalogRealTimeValue();       //刷新给显示层用的数据.
        }
        /// <summary>
        /// 处理选定模拟量实时值回执。
        /// 放入实时值缓冲区时，如果实时值缓冲区已经初始化，则直接改变缓冲区的值，否则首先根据实时值的个数初始化划缓冲区。
        /// </summary>
        /// <param name="sBuf"></param>
        /// <param name="offset"></param>
        private static void DisposeSpecialAnalogRealTimeValue(byte[] sBuf, int offset)
        {
            int m = offset;
            int rNum = sBuf[m] + (sBuf[m + 1] << 8);
            m+=2;
            int time = sBuf[m] + (sBuf[m + 1] << 8) + (sBuf[m + 2] << 16) + (sBuf[m + 3] << 24);
            m += 4;
            for (int i = 0; i < rNum; i++)
            {
                byte type = (byte)(sBuf[m] + (sBuf[m + 1] << 8));
                m += 2;
                int idx = sBuf[m] + (sBuf[m + 1] << 8);
                m += 2;
                Int16 v = (Int16)(sBuf[m] + (sBuf[m + 1] << 8));
                m += 2;
                if (c_RealTimeValue.ReceiveAnalogData.ContainsKey(type))
                {
                    if (c_RealTimeValue.ReceiveAnalogData[type].Count > idx)    //实时值缓冲区内有该值的位置
                    {
                        c_RealTimeValue.ReceiveAnalogData[type][idx] = v;
                    }
                }
                else
                {
                    string typeName = c_Device.GetAnalogTypeName((AnalogCodeType)type);
                    int AllNum = c_Device.GetAnalogTypeDevNum(typeName);
                    List<Int16> Init = new List<short>();
                    for (int j = 0; j < AllNum; j++) Init.Add(-1);   
                    c_RealTimeValue.ReceiveAnalogData.Add(type, Init);  //初始化实时值缓冲区
                    if (idx < AllNum)
                    {
                        c_RealTimeValue.ReceiveAnalogData[type][idx] = v;
                    }
                }
            }
            c_RealTimeValue.DisposeAnalogRealTimeValue();       //刷新给显示层用的数据.
        }
        /// <summary>
        /// 处理模拟量最新值回执，绝缘、漏流、残压最新值
        /// </summary>
        /// <param name="type"></param>
        /// <param name="st"></param>
        /// <param name="offset"></param>
        private static void DisposeNewstRealTimeValue(byte type, byte[] st, int offset)
        {
            int m = offset;
            int rNum = st[m] + (st[m + 1] << 8);
            m+=2;
            for (int i = 0; i < rNum; i++)
            {
                int v = st[m] + (st[m + 1] << 8);
                m += 2;
                int t = st[m] + (st[m + 1] << 8) + (st[m + 2] << 16) + (st[m + 3] << 24);
                m += 4;
                objCodeDev key = new objCodeDev();
                key.codetype = type;
                key.dev_no = (Int16)i;
                if (c_RealTimeValue.JyLlCyRealTimeValue.Keys.Contains(key)) c_RealTimeValue.JyLlCyRealTimeValue.Remove(key);
                objTV tv = new objTV();
                tv.utime = t;
                tv.value = (Int16)v;
                c_RealTimeValue.JyLlCyRealTimeValue.Add(key, tv);
                if (type == 0x80) //绝缘
                {
                    ObjValue ft = c_RealTimeValue.ConvertAnalogValue("绝缘", (Int16)v);
                    float value = ft.Value;
                    if (i >= 0 && i < c_RealTimeValue.JyRealTimeTable.Rows.Count)
                    {
                        DataRow dr = c_RealTimeValue.JyRealTimeTable.Rows[i];
                        dr.BeginEdit();
                        if (value == 0xffff) dr["测试值"] = "----";
                        else dr["测试值"] = value.ToString();

                        if (t == 0) dr["测试时间"] = "----";
                        else
                        {
                            DateTime u = MySql.Time_tToDateTime(t);
                            dr["测试时间"] = u.ToString();
                        }
                        dr.EndEdit();
                    }
                }
                else if (type == 0x81)
                {
                    ObjValue ft = c_RealTimeValue.ConvertAnalogValue("漏流", (Int16)v);
                    float value = ft.Value;
                    if (i >= 0 && i < c_RealTimeValue.LlRealTimeTable.Rows.Count)
                    {
                        DataRow dr = c_RealTimeValue.LlRealTimeTable.Rows[i];
                        dr.BeginEdit();
                        if (value == 0xffff) dr["测试值"] = "----";
                        else dr["测试值"] = value.ToString();

                        if (t == 0) dr["测试时间"] = "----";
                        else
                        {
                            DateTime u = MySql.Time_tToDateTime(t);
                            dr["测试时间"] = u.ToString();
                        }
                        dr.EndEdit();
                    }
                }
                else if (type == 0x24)
                {
                    //ObjValue ft = c_RealTimeValue.ConvertAnalogValue("残压", (Int16)v);
                    //float value = ft.Value;
                    //if (i >= 0 && i < c_RealTimeValue.CyRealTimeTable.Rows.Count)
                    //{
                    //    DataRow dr = c_RealTimeValue.RealTimeTable.Rows[i];
                    //    dr.BeginEdit();
                    //    if (value == 0xffff) dr["测试值"] = "----";
                    //    else dr["测试值"] = value.ToString();

                    //    if (t == 0) dr["测试时间"] = "----";
                    //    else
                    //    {
                    //        DateTime u = MySql.Time_tToDateTime(t);
                    //        dr["测试时间"] = u.ToString();
                    //    }
                    //    dr.EndEdit();
                    //}
                }
            }
        }
        /// <summary>
        /// 获取时间列表信息，直接从程序运行表里面取数据,回执终端获取日报表时间命令。
        /// </summary>
        private static void DisposeGetTimeList(object o)
        {
            objNetCode obj = (objNetCode)o;
            ProgarmRunTimeTable tb = new ProgarmRunTimeTable();
            tb.Read_TimeList();
            List<int> TimeList = new List<int>();
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                if (tb.ReadyRead)
                {
                    foreach(objDate d in tb.RunTimeList.Keys)
                    {
                        DateTime t = new DateTime(d.year,d.month,d.day,0,0,0);
                        int ti = (int)MySql.DateTimeToTime_t(t);
                        TimeList.Add(ti);
                    }
                    break;
                }
                else
                {
                    Thread.Sleep(300);
                }
            }
            c_NetCom.RetSendDailyReportTimeData(obj.sCode, obj.type, TimeList);
        }
        /// <summary>
        /// 处理终端提取日报表命令
        /// 流程：读数据库，数据库读成功后，调用发送函数发送
        /// </summary>
        /// <param name="o"></param>
        private static void DisposeGetDailyReportData(object o)
        {
            objNetCode obj = (objNetCode)o;
            DailyReportTable db = new DailyReportTable();
            DateTime time = MySql.Time_tToDateTime(obj.utime);
            objDate date = new objDate();
            date.year = time.Year;
            date.month = (byte)time.Month;
            date.day = (byte)time.Day;
            db.ReadDailyReportValueList(date, obj.type);
            List<objDailyReport> li = new List<objDailyReport>();
            while (true)
            {
                if (db.DailyReportErrorFlag != 0) break;
                if (db.Ready_OneTypeDailyReportData)
                {
                    AnalogCodeType key = (AnalogCodeType)obj.type;
                    if (db.DailyReportAnalogValueList.Keys.Contains(key))
                    {                       
                        for(int i =0 ;i<db.DailyReportAnalogValueList[key].Count;i++)
                        {
                            objDailyReport drt = db.DailyReportAnalogValueList[key][i];
                            li.Add(drt);
                        }
                        break;
                    }
                }
            }
            c_NetCom.RetSendSendDailyReportValueData(obj.sCode, obj.type, obj.utime, li);
        }
        /// <summary>
        /// 终端接收日报表时间列表
        /// </summary>
        /// <param name="type"></param>
        /// <param name="st"></param>
        /// <param name="offset"></param>
        private static void tDisposeRevDailyReportTimeList(byte type, byte[] st, int offset)
        {
            int m = offset;
            int rNum = st[m] + (st[m + 1] << 8);
            m += 2;
            for (int i = 0; i < rNum; i++)
            {
                int u = st[m] + (st[m + 1] << 8) + (st[m + 2] << 16) + (st[m + 3] << 24);
                DateTime t = MySql.Time_tToDateTime(u);
                DailyReportTimeList.Add(t);
                m += 4;
            }
        }
        /// <summary>
        /// 终端接收日报表数据
        /// </summary>
        /// <param name="type"></param>
        /// <param name="st"></param>
        /// <param name="offset"></param>
        private static void tDisposeRevDailyReportData(byte type, byte[] st, int offset)
        {
            int m = offset;
            int u = st[m] + (st[m + 1] << 8) + (st[m + 2] << 16) + (st[m + 3] << 24); //报表时间
            m += 4;
            int rNum = st[m] + (st[m + 1] << 8); //记录数
            m += 2;
            List<objDailyReport> dt = new List<objDailyReport>();
            string ts = c_Device.GetAnalogTypeName((AnalogCodeType)type);
            for (int i = 0; i < rNum; i++)
            {
                int Maxv = st[m] + (st[m + 1] << 8);
                m += 2;
                int Maxt = st[m] + (st[m + 1] << 8) + (st[m + 2] << 16) + (st[m + 3] << 24);
                m += 4;
                int Minv = st[m] + (st[m + 1] << 8);
                m += 2;
                int Mint = st[m] + (st[m + 1] << 8) + (st[m + 2] << 16) + (st[m + 3] << 24);
                m += 4;
                int Avrv = st[m] + (st[m + 1] << 8);
                m += 2;
                int Avrt = st[m] + (st[m + 1] << 8) + (st[m + 2] << 16) + (st[m + 3] << 24);
                m += 4;
                objDailyReport tdt = new objDailyReport();
                tdt.analog_no = (short)i;

                tdt.bMaxValue = (short)Maxv;
                tdt.MaxValue = c_RealTimeValue.ConvertAnalogValue(ts,(short)Maxv);
                tdt.MaxTime = Maxt;

                tdt.bMinValue = (short)Minv;
                tdt.MinValue = c_RealTimeValue.ConvertAnalogValue(ts, (short)Minv);
                tdt.MinTime = Mint;

                tdt.bAvrValue = (short)Avrv;
                tdt.AvrValue = c_RealTimeValue.ConvertAnalogValue(ts, (short)Avrv);
                tdt.AvrTime = Avrt;
                dt.Add(tdt);
            }
            if(DailyReportAnalogValueList.ContainsKey(type))DailyReportAnalogValueList.Remove(type);
            DailyReportAnalogValueList.Add(type, dt);
        }
        /// <summary>
        /// 站机处理日曲线时间记录
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetDailyCurveTimeList(object o)
        {
            objNetCode obj = (objNetCode)o;
            ProgarmRunTimeTable tb = new ProgarmRunTimeTable();
            tb.Read_TimeList();
            List<int> TimeList = new List<int>();
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                if (tb.ReadyRead)
                {
                    foreach (objDate d in tb.RunTimeList.Keys)
                    {
                        DateTime Now = DateTime.Now;
                        DateTime t = new DateTime(d.year, d.month, d.day, 0, 0, 0);
                        //只取前30天的数据
                        TimeSpan tspan= Now - t;
                        if (tspan.Days <= 31)   //日曲线只取30天的数据
                        {
                            int ti = (int)MySql.DateTimeToTime_t(t);
                            TimeList.Add(ti);
                        }
                    }
                    break;
                }
                else
                {
                    Thread.Sleep(300);
                }
            }
            int stime = TimeList.Min();
            int etime = TimeList.Max();
            c_NetCom.RetSendAnalogDailyCurveTimeData(obj.sCode, obj.type, stime, etime);
        }
        /// <summary>
        /// 站机处理日曲线数据命令
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetDailyCurveData(object o)
        {
            objNetCode obj = (objNetCode)o;
            int stime = obj.stime;
            int etime = obj.etime;
            byte devType = obj.sontype;
            int devNo = obj.DevNo;
            string Dcode = obj.sCode;
            DateTime dtime = MySql.Time_tToDateTime(stime);
            DateTime pday = MySql.Time_tToDateTime(stime);
            TimeSpan ts = dtime - StationDailyCurveDay;     //开始时间-缓冲区的时间，是否是缓冲区保存的数据.
            objCodeDev key = new objCodeDev();
            key.codetype = devType;
            key.dev_no = (short)devNo;

            //首先判断是否回溯时间
            TimeAdjustTable tbhs = new TimeAdjustTable();
            tbhs.ReadValueList();
            int TimeRecallNum = 0;  //时间回溯次数
            int sRecallTime = 0;    //时间重复开始时间
            int eRecallTime = 0;    //时间重复结束时间
            while (true)
            {
                if (tbhs.ErrorFlag != 0) break;
                else if (tbhs.ReadyValueList)
                {
                    for(int i = 0;i<tbhs.ValueList.Count;i++)
                    {
                        ///统计了整个时间段内的调整时间，取的最后一次的调整时间
                        if (tbhs.ValueList[i].btime >= stime && tbhs.ValueList[i].ftime <= etime)
                        {
                            //回溯的时间段在整个时间段内
                            TimeRecallNum++;
                            sRecallTime = tbhs.ValueList[i].btime;
                            eRecallTime = tbhs.ValueList[i].ftime;
                            break;  //当前协议只支持一次回溯，找到一次就退出
                        }
                        else if (tbhs.ValueList[i].btime <= stime && tbhs.ValueList[i].ftime >= stime)
                        {
                            //开始时间包含在调整时间段内，///那重复时间的开始时间就是 本次调取的开始时间
                            TimeRecallNum++;
                            //sRecallTime = tbhs.ValueList[i].btime;
                            sRecallTime = stime;
                            eRecallTime = tbhs.ValueList[i].ftime;
                            break;
                        }
                        else if (tbhs.ValueList[i].btime <= etime && tbhs.ValueList[i].ftime >= etime)
                        {
                            //结束时间包含在调整时间段内,那重复时间的结束时间就是本次调取的结束时间
                            TimeRecallNum++;
                            sRecallTime = tbhs.ValueList[i].btime;
                            ///eRecallTime = tbhs.ValueList[i].ftime;
                            eRecallTime = etime;
                            break;
                        }
                    }
                    break;
                }
                else Thread.Sleep(300);
            }
            if (TimeRecallNum != 0) //有回溯
            {
                ///发送日曲线回溯信息。
                c_NetCom.RetSendDailyCurveTimeRecallData(Dcode, devType, TimeRecallNum + 1, sRecallTime, eRecallTime);
            }
            else
            {
                if (ts.Days == 0 && StationDailyCurveValueList.Keys.Contains(key))    //时间和类型，设备序号都对，缓冲区内有数据，则不读数据库
                { }
                else
                {
                    if (ts.Days == 0) //换天后，清除数据
                    {
                        StationDailyCurveDay = new DateTime(1970, 1, 1);
                        StationDailyCurveValueList.Clear();
                    }
                    AnalogTable tb = new AnalogTable();
                    tb.ReadDailyValueList(devType, devNo, pday);
                    while (true)
                    {
                        if (tb.ErrorFlag != 0) break;
                        if (tb.Ready_DailyCurveValueList)
                        {
                            StationDailyCurveValueList = Clone(tb.TermianlValueList) as Dictionary<objCodeDev, List<objTimeValue>>;
                            StationDailyCurveDay = dtime;
                            break;
                        }
                        else Thread.Sleep(300);
                    }
                }
                //组织数据
                
                List<objTimeValue> SendList = new List<objTimeValue>();
                if (StationDailyCurveValueList.Keys.Contains(key))
                {
                    foreach (objTimeValue t in StationDailyCurveValueList[key])
                    {
                        if (t.u_time >= stime && t.u_time <= etime)
                        {
                            SendList.Add(t);
                        }
                    }

                    ///以下为补齐数据的发送方式，如果不补齐数据，直接发送t6的数据.
                    ///数据补齐，补到每秒都有数据
                    List<objTimeValue> t6 = new List<objTimeValue>(SendList);
                    List<objTimeValue> t7 = new List<objTimeValue>();

                    objTimeValue firstObj = new objTimeValue();
                    objTimeValue NextObj = new objTimeValue();
                    for (int i = 0; i < t6.Count - 1; i++)      //补中间的差点
                    {
                        firstObj = t6[i];
                        NextObj = t6[i + 1];
                        int needdot = NextObj.u_time - firstObj.u_time - 1;
                        t7.Add(firstObj);
                        objTimeValue bdot = new objTimeValue();
                        bdot = firstObj;
                        if (needdot > 10)
                        {
                            bdot.Dvalue = -1;
                        }                        
                        for (int j = 0; j < needdot; j++)
                        {                         
                            bdot.u_time++;
                            t7.Add(bdot);                        
                        }
                    }
                    t7.Add(t6[t6.Count - 1]);   //把t6的最后一个点加进去
                    int needdot1 = etime - t6[t6.Count - 1].u_time;
                    objTimeValue bdot1 = new objTimeValue();
                    bdot1 = t6[t6.Count - 1];
                    for (int i = 0; i < needdot1; i++)  //补最后一个有效点到结束时间的点。
                    {
                        bdot1.u_time++;
                        t7.Add(bdot1);
                    }

                    c_NetCom.RetSendAnalogDailyCurveData(Dcode, devType, (short)devNo, t7);   //往网络发送数据
                }
                else
                {
                    c_NetCom.RetSendAnalogDailyCurveData(Dcode, devType, (short)devNo, SendList);   //往网络发送数据,没取到数据，发送空数据
                }
            }
        }
        /// <summary>
        /// 站机发送回溯段时间数据
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetDailyCurveDataRecall(object o)
        {
            objNetCode obj = (objNetCode)o;
            int stime = obj.stime;
            int etime = obj.etime;
            int srecalltime = obj.recallstime;
            int erecalltime = obj.recalletime;
            int recallnum = obj.recallNum;
            byte devType = obj.sontype;
            int devNo = obj.DevNo;
            string Dcode = obj.sCode;
            DateTime dtime = MySql.Time_tToDateTime(stime);
            DateTime pday =  MySql.Time_tToDateTime(stime);
            TimeSpan ts = dtime - StationDailyCurveDay;
            objCodeDev key = new objCodeDev();
            key.codetype = devType;
            key.dev_no = (short)devNo;

            if (ts.Days == 0 && StationDailyCurveValueList.Keys.Contains(key))    //时间和类型，设备序号都对，则不读数据库
            { }
            else
            {
                if (ts.Days == 0) //换天后，清除数据
                {
                    StationDailyCurveDay = new DateTime(1970, 1, 1);
                    StationDailyCurveValueList.Clear();
                }
                AnalogTable tb = new AnalogTable();
                tb.ReadDailyValueList(devType, devNo, pday);
                while (true)
                {
                    if (tb.ErrorFlag != 0) break;
                    if (tb.Ready_DailyCurveValueList)
                    {
                        StationDailyCurveValueList = Clone(tb.TermianlValueList) as Dictionary<objCodeDev, List<objTimeValue>>;
                        StationDailyCurveDay = dtime;
                        break;
                    }
                    else Thread.Sleep(300);
                }
            }
            ///组织数据
            List<objTimeValue> SendList = new List<objTimeValue>();
            if (StationDailyCurveValueList.Keys.Contains(key))
            {
                foreach (objTimeValue t in StationDailyCurveValueList[key])
                {
                    if (t.u_time >= stime && t.u_time <= etime)
                    {
                        SendList.Add(t);    //找到符合开始时间和结束时间条件的数据
                    }
                }
                ///把重复的数据挑出来
                List<objTimeValue> t1 = new List<objTimeValue>();   //回溯时间段前的数据
                List<objTimeValue> t2 = new List<objTimeValue>();   //回溯时间段的数据
                List<objTimeValue> t3 = new List<objTimeValue>();   //回溯时间段后的数据

                foreach (objTimeValue t in SendList)
                {
                    if (t.u_time < srecalltime)
                    {
                        t1.Add(t);
                    }
                    else if (t.u_time > erecalltime)
                    {
                        t3.Add(t);
                    }
                    else
                    {
                        t2.Add(t);
                    }
                }
                List<objTimeValue> t4 = new List<objTimeValue>();   //重复时间段时间调整前的数据
                List<objTimeValue> t5 = new List<objTimeValue>();   //重复时间段时间调整后的数据

                foreach (objTimeValue t in t2)      //重复段的数据分段，
                {
                    bool reflag = false;    //重复标记
                    foreach (objTimeValue f in t4)
                    {
                        if (t.u_time == f.u_time)
                        {
                            t5.Add(t);      //是重复的数据，放入到t5中
                            reflag = true;
                            break;
                        }
                    }
                    if (reflag == false) t4.Add(t);
                }
                List<objTimeValue> t6 = new List<objTimeValue>();
                t6.AddRange(t1);        //回溯前的数据
                if (recallnum == 0)
                {
                    t6.AddRange(t4);    //第0段的数据
                }
                else
                {
                    t6.AddRange(t5);    //第1段的数据
                }
                t6.AddRange(t3);        //回溯时间段后的数据

                ///以下为补齐数据的发送方式，如果不补齐数据，直接发送t6的数据.
                ///数据补齐，补到每秒都有数据
                List<objTimeValue> t7 = new List<objTimeValue>();
                int dotNum = etime - stime;
                objTimeValue firstObj = new objTimeValue();
                objTimeValue NextObj = new objTimeValue();
                for (int i = 0; i < t6.Count - 1; i++)      //补中间的差点
                {
                    firstObj = t6[i];
                    NextObj = t6[i + 1];
                    int needdot = NextObj.u_time - firstObj.u_time - 1;
                    t7.Add(firstObj);
                    objTimeValue bdot = new objTimeValue();
                    bdot = firstObj;
                    if (needdot > 10)   //超过10s 认为是无效数据
                    {
                        bdot.Dvalue = -1;
                    }
                    for (int j = 0; j < needdot; j++)
                    {
                        bdot.u_time++;
                        t7.Add(bdot);
                    }
                }
                t7.Add(t6[t6.Count - 1]);   //把t6的最后一个点加进去
                int needdot1 = etime - t6[t6.Count - 1].u_time;
                objTimeValue bdot1 = new objTimeValue();
                bdot1 = t6[t6.Count - 1];
                for (int i = 0; i < needdot1; i++)  //补最后一个有效点到结束时间的点。
                {
                    bdot1.u_time++;
                    t7.Add(bdot1);
                }

                c_NetCom.RetSendAnalogDailyCurveData(Dcode, devType, (short)devNo, t7);   //往网络发送数据
            }
            else
            {
                c_NetCom.RetSendAnalogDailyCurveData(Dcode, devType, (short)devNo, SendList);   //往网络发送空数据
            }
        }
        /// <summary>
        /// 站机处理高频日曲线命令
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetDailyHigFrequencyData(object o)
        {
            objNetCode obj = (objNetCode)o;
            int stime = obj.stime;
            int etime = obj.etime;
            byte devType = obj.sontype;
            int devNo = obj.DevNo;
            string Dcode = obj.sCode;
            DateTime dtime = MySql.Time_tToDateTime(stime);
            DateTime pday = MySql.Time_tToDateTime(stime);
            TimeSpan ts = dtime - StationDailyHigFrequencyDay;     //开始时间-缓冲区的时间，是否是缓冲区保存的数据.
            objCodeDev key = new objCodeDev();
            key.codetype = devType;
            key.dev_no = (short)devNo;

            //首先判断是否回溯时间
            TimeAdjustTable tbhs = new TimeAdjustTable();
            tbhs.ReadValueList();
            int TimeRecallNum = 0;  //时间回溯次数
            int sRecallTime = 0;    //时间重复开始时间
            int eRecallTime = 0;    //时间重复结束时间
            while (true)
            {
                if (tbhs.ErrorFlag != 0) break;
                else if (tbhs.ReadyValueList)
                {
                    for(int i = 0;i<tbhs.ValueList.Count;i++)
                    {
                        ///统计了整个时间段内的调整时间，取的最后一次的调整时间
                        if (tbhs.ValueList[i].btime >= stime && tbhs.ValueList[i].ftime <= etime)
                        {
                            //回溯的时间段在整个时间段内
                            TimeRecallNum++;
                            sRecallTime = tbhs.ValueList[i].btime;
                            eRecallTime = tbhs.ValueList[i].ftime;
                            break;  //当前协议只支持一次回溯，找到一次就退出
                        }
                        else if (tbhs.ValueList[i].btime <= stime && tbhs.ValueList[i].ftime >= stime)
                        {
                            //开始时间包含在调整时间段内，///那重复时间的开始时间就是 本次调取的开始时间
                            TimeRecallNum++;
                            //sRecallTime = tbhs.ValueList[i].btime;
                            sRecallTime = stime;
                            eRecallTime = tbhs.ValueList[i].ftime;
                            break;
                        }
                        else if (tbhs.ValueList[i].btime <= etime && tbhs.ValueList[i].ftime >= etime)
                        {
                            //结束时间包含在调整时间段内,那重复时间的结束时间就是本次调取的结束时间
                            TimeRecallNum++;
                            sRecallTime = tbhs.ValueList[i].btime;
                            ///eRecallTime = tbhs.ValueList[i].ftime;
                            eRecallTime = etime;
                            break;
                        }
                    }
                    break;
                }
                else Thread.Sleep(300);
            }
            if (TimeRecallNum != 0) //有回溯
            {
                ///发送日曲线回溯信息。
                c_NetCom.RetSendHighFrequencyRecallTime(Dcode, devType, TimeRecallNum + 1, sRecallTime, eRecallTime);
            }
            else
            {
                if (ts.Days == 0 && StationDailyHigFrequencyValueList.Keys.Contains(key))    //时间和类型，设备序号都对，缓冲区内有数据，则不读数据库
                { }
                else
                {
                    if (ts.Days == 0) //换天后，清除数据
                    {
                        StationDailyHigFrequencyDay = new DateTime(1970, 1, 1);
                        StationDailyHigFrequencyValueList.Clear();
                    }
                    AnalogHigFreTable tb = new AnalogHigFreTable();
                    tb.ReadDailyValueList(devType, devNo, pday);
                    while (true)
                    {
                        if (tb.ErrorFlag != 0) break;
                        if (tb.Ready_DailyCurveValueList)
                        {
                            StationDailyHigFrequencyValueList = Clone(tb.TermianlValueList) as Dictionary<objCodeDev, List<HigFreAnalogValue>>;
                            StationDailyHigFrequencyDay = dtime;
                            break;
                        }
                        else Thread.Sleep(300);
                    }
                }
                //组织数据
                List<HigFreAnalogValue> SendList = new List<HigFreAnalogValue>();
                int freq = 0;
                if (StationDailyHigFrequencyValueList.Keys.Contains(key))
                {
                    foreach (HigFreAnalogValue t in StationDailyHigFrequencyValueList[key])
                    {
                        if (t.utime >= stime && t.utime <= etime)
                        {
                            if (t.SecondValueList.Count > freq)
                            {
                                freq = t.SecondValueList.Count;
                            }
                            SendList.Add(t);
                        }
                    }
                    ///无需填充数据
                    c_NetCom.RetSendHighFrequencyAnalogData(Dcode, devType, (short)devNo, freq, SendList);   //往网络发送数据
                }
            }
        }
        /// <summary>
        /// 站机处理高频日曲线时间回溯命令
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetHigFrequencyDataRecall(object o)
        {
            objNetCode obj = (objNetCode)o;
            int stime = obj.stime;
            int etime = obj.etime;
            int srecalltime = obj.recallstime;
            int erecalltime = obj.recalletime;
            int recallnum = obj.recallNum;
            byte devType = obj.sontype;
            int devNo = obj.DevNo;
            string Dcode = obj.sCode;
            DateTime dtime = MySql.Time_tToDateTime(stime);
            DateTime pday = MySql.Time_tToDateTime(stime);
            TimeSpan ts = dtime - StationDailyHigFrequencyDay;  //站机高频曲线保留天
            objCodeDev key = new objCodeDev();
            key.codetype = devType;
            key.dev_no = (short)devNo;

            if (ts.Days == 0 && StationDailyHigFrequencyValueList.Keys.Contains(key))    //时间和类型，设备序号都对，则不读数据库
            { }
            else
            {
                if (ts.Days == 0) //换天后，清除数据
                {
                    StationDailyHigFrequencyDay = new DateTime(1970, 1, 1);
                    StationDailyHigFrequencyValueList.Clear();
                }
                AnalogHigFreTable tb = new AnalogHigFreTable();
                tb.ReadDailyValueList(devType, devNo, pday);
                while (true)
                {
                    if (tb.ErrorFlag != 0) break;
                    if (tb.Ready_DailyCurveValueList)
                    {
                        StationDailyHigFrequencyValueList = Clone(tb.TermianlValueList) as Dictionary<objCodeDev, List<HigFreAnalogValue>>;
                        StationDailyHigFrequencyDay = dtime;
                        break;
                    }
                    else Thread.Sleep(300);
                }
            }
            ///组织数据
            List<HigFreAnalogValue> SendList = new List<HigFreAnalogValue>();
            if (StationDailyCurveValueList.Keys.Contains(key))
            {
                foreach (HigFreAnalogValue t in StationDailyHigFrequencyValueList[key])
                {
                    if (t.utime >= stime && t.utime <= etime)
                    {
                        SendList.Add(t);    //找到符合开始时间和结束时间条件的数据
                    }
                }
                ///把重复的数据挑出来
                List<HigFreAnalogValue> t1 = new List<HigFreAnalogValue>();   //回溯时间段前的数据
                List<HigFreAnalogValue> t2 = new List<HigFreAnalogValue>();   //回溯时间段的数据
                List<HigFreAnalogValue> t3 = new List<HigFreAnalogValue>();   //回溯时间段后的数据

                foreach (HigFreAnalogValue t in SendList)
                {
                    if (t.utime < srecalltime)
                    {
                        t1.Add(t);
                    }
                    else if (t.utime > erecalltime)
                    {
                        t3.Add(t);
                    }
                    else
                    {
                        t2.Add(t);
                    }
                }
                List<HigFreAnalogValue> t4 = new List<HigFreAnalogValue>();   //重复时间段时间调整前的数据
                List<HigFreAnalogValue> t5 = new List<HigFreAnalogValue>();   //重复时间段时间调整后的数据

                foreach (HigFreAnalogValue t in t2)      //重复段的数据分段，
                {
                    bool reflag = false;    //重复标记
                    foreach (HigFreAnalogValue f in t4)
                    {
                        if (t.utime == f.utime)
                        {
                            t5.Add(t);      //是重复的数据，放入到t5中
                            reflag = true;
                            break;
                        }
                    }
                    if (reflag == false) t4.Add(t);
                }
                List<HigFreAnalogValue> t6 = new List<HigFreAnalogValue>();
                t6.AddRange(t1);        //回溯前的数据
                if (recallnum == 0)
                {
                    t6.AddRange(t4);    //第0段的数据
                }
                else
                {
                    t6.AddRange(t5);    //第1段的数据
                }
                t6.AddRange(t3);        //回溯时间段后的数据

                int freq = 0;
                if (t6.Count >= 1)
                {
                    freq = t6[0].SecondValueList.Count;
                }                
                c_NetCom.RetSendHighFrequencyAnalogData(Dcode, devType, (short)devNo,freq, t6);   //往网络发送数据
            }
            else
            {
                c_NetCom.RetSendHighFrequencyAnalogData(Dcode, devType, (short)devNo, 0, SendList);   //往网络发送空数据
            }
        }
        /// <summary>
        /// 站机处理开关量回放时间
        /// </summary>
        /// <param name="o"></param>
        private static void DisposeGetKglTimeList(object o)
        {
            objNetCode obj = (objNetCode)o;
            ProgarmRunTimeTable tb = new ProgarmRunTimeTable();
            tb.Read_TimeList();
            List<int> TimeList = new List<int>();
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                if (tb.ReadyRead)
                {
                    foreach (objDate d in tb.RunTimeList.Keys)
                    {
                        DateTime t = new DateTime(d.year, d.month, d.day, 0, 0, 0);
                        int ti = (int)MySql.DateTimeToTime_t(t);
                        TimeList.Add(ti);
                    }
                    break;
                }
                else
                {
                    Thread.Sleep(300);
                }
            }
            c_NetCom.RetSendKGLReplayTimeData(obj.sCode, TimeList.Min(), TimeList.Max());
        }
        /// <summary>
        /// 把从数据中读到的开关量数据转换成要发送的字节数组
        /// </summary>
        /// <param name="KGL_ValueList"></param>
        /// <param name="RecallFlag"></param>
        /// <param name="stime"></param>
        /// <param name="etime"></param>
        /// <returns></returns>
        private static List<byte> TidyKglReplayData(List<ObjKGL> KGL_ValueList, bool RecallFlag, int stime, int etime)
        {
            List<byte> Ti = new List<byte>();
            byte rflag = 0;
            if (RecallFlag) rflag = 0x42;
            else rflag = 0x41;
            Ti.Add(rflag);
            byte[] time = new byte[4];
            time = BitConverter.GetBytes(stime);
            Ti.AddRange(time);
            time = new byte[4];
            time = BitConverter.GetBytes(etime);
            Ti.AddRange(time);
            int allrNum = 0;   //总记录数
            foreach (ObjKGL key in KGL_ValueList)
            {
                if (key.type == 0x01) allrNum++;       //全体开关量记录数.
                else
                {
                   allrNum += key.len / 2;             //每个变化时一个变化开关量的记录
                }
            }
            byte[] all = new byte[2];
            all = BitConverter.GetBytes(allrNum);
            Ti.AddRange(all);
            //----------------------
            int allNum = c_Device.KGL_Config.Count; //开关量总路数
            all = new byte[4];
            all = BitConverter.GetBytes(allNum);
            Ti.AddRange(all);
            //-----------------------
            int allRecordNum = 0;
            foreach (ObjKGL key in KGL_ValueList)
            {
                if (key.type == 0x01) allRecordNum++;       //全体开关量记录数.
            }
            all = new byte[2];
            all = BitConverter.GetBytes(allRecordNum);
            Ti.AddRange(all);
            //-------------------------
            //-----下面处理索引.            
            List<int> idxSet = new List<int>();
            int sidx = 17;
            for (int i = 0; i < KGL_ValueList.Count; i++)
            {
                if (KGL_ValueList[i].type == 0x01)
                {
                    idxSet.Add(sidx);
                    sidx += KGL_ValueList[i].len;   //本次全体开关量的字节数
                    sidx += 7;                      //还有7个全体的头字节
                }
                else   //变化开关量
                {
                    //变化开关量要拆开来计算字节数. 变化开关量个数 = 变化开关量长度/2.
                    int clen = KGL_ValueList[i].len;
                    int ct = clen / 2;
                    sidx += ct * 7;     //每个变化开关量7个字节
                }
            }

            for (int i = 0; i < idxSet.Count; i++)
            {
                byte[] bi = new byte[4];
                int k = idxSet[i];
                k += allRecordNum * 4;              //必须加上索引所占的字节数
                bi = BitConverter.GetBytes(k);
                Ti.AddRange(bi);    //把索引加入到缓冲区中
            }
            //------------------------------------------
            foreach (ObjKGL key in KGL_ValueList)
            {
                if (key.type == 0x01)
                {
                    Ti.Add(0x01);
                    byte[] tmp = new byte[2];
                    tmp = BitConverter.GetBytes(c_Device.KGL_Config.Count); //全体开关量总数
                    Ti.AddRange(tmp);
                    tmp = new byte[4];
                    tmp = BitConverter.GetBytes(key.u_time);
                    Ti.AddRange(tmp);
                    for (int i = 0; i < key.len; i++)
                    {
                        Ti.Add(key.v[i]);     //数据加入到整理缓冲区
                    }
                }
                else
                {
                    byte[] tmp = new byte[4];
                    tmp = BitConverter.GetBytes(key.u_time);
                    int clen = key.len;
                    int ct = clen / 2;      //变化开关量个数
                    int j = 0;
                    for (int i = 0; i < ct; i++)
                    {
                        Ti.Add(0x00);
                        Ti.AddRange(tmp);   //时间
                        Ti.Add(key.v[j]);
                        Ti.Add(key.v[j + 1]);
                        j += 2;
                    }
                }
            }
            return Ti;
        }
        /// <summary>
        /// 站机处理提取开关量数据命令
        /// </summary>
        /// <param name="o"></param>
        private static void DisposeGetKglReplayData(object o)
        {
            objNetCode obj = (objNetCode)o;
            int stime = obj.stime;
            int etime = obj.etime;
            string Dcode = obj.sCode;

            //首先判断是否回溯时间
            TimeAdjustTable tbhs = new TimeAdjustTable();
            tbhs.ReadValueList();
            int TimeRecallNum = 0;  //时间回溯次数
            int sRecallTime = 0;    //时间重复开始时间
            int eRecallTime = 0;    //时间重复结束时间
            while (true)
            {
                if (tbhs.ErrorFlag != 0) break;
                else if (tbhs.ReadyValueList)
                {
                    for (int i = 0; i < tbhs.ValueList.Count; i++)
                    {
                        ///统计了整个时间段内的调整时间，取的最后一次的调整时间
                        if (tbhs.ValueList[i].btime >= stime && tbhs.ValueList[i].ftime <= etime)
                        {
                            //回溯的时间段在整个时间段内
                            TimeRecallNum++;
                            sRecallTime = tbhs.ValueList[i].btime;
                            eRecallTime = tbhs.ValueList[i].ftime;
                            break;  //当前协议只支持一次回溯，找到一次就退出
                        }
                        else if (tbhs.ValueList[i].btime <= stime && tbhs.ValueList[i].ftime >= stime)
                        {
                            //开始时间包含在调整时间段内，///那重复时间的开始时间就是 本次调取的开始时间
                            TimeRecallNum++;
                            //sRecallTime = tbhs.ValueList[i].btime;
                            sRecallTime = stime;
                            eRecallTime = tbhs.ValueList[i].ftime;
                            break;
                        }
                        else if (tbhs.ValueList[i].btime <= etime && tbhs.ValueList[i].ftime >= etime)
                        {
                            //结束时间包含在调整时间段内,那重复时间的结束时间就是本次调取的结束时间
                            TimeRecallNum++;
                            sRecallTime = tbhs.ValueList[i].btime;
                            ///eRecallTime = tbhs.ValueList[i].ftime;
                            eRecallTime = etime;
                            break;
                        }
                    }
                    break;
                }
                else Thread.Sleep(300);
            }
            if (TimeRecallNum != 0) //有回溯
            {
                ///发送开关量回溯信息。
                c_NetCom.RetSendKGLHistoryRecallInfo(Dcode, TimeRecallNum + 1, sRecallTime, eRecallTime);
            }
            else   //无回溯
            {
                List<ObjKGL> KGL_ValueList = new List<ObjKGL>();
                KGL_Table tb = new KGL_Table();
                tb.Read_KGL_ValueList(stime,etime);
                while (true)
                {
                    if (tb.ErrorFlag != 0) break;
                    if (tb.Ready_KGL_ValueList)
                    {
                        KGL_ValueList = Clone(tb.KGL_ValueList) as List<ObjKGL>;
                        break;
                    }
                    else Thread.Sleep(300);
                }
                //以下组织数据
                List<byte> sendBuf = TidyKglReplayData(KGL_ValueList, false, stime, etime);
                c_NetCom.RetSendKGLReplayData(Dcode, sendBuf);
            }
        }
        /// <summary>
        /// 站机处理提取开关量回溯数据命令
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetkglDataRecall(object o)
        {
            objNetCode obj = (objNetCode)o;
            int stime = obj.stime;
            int etime = obj.etime;
            int srecalltime = obj.recallstime;
            int erecalltime = obj.recalletime;
            int recallnum = obj.recallNum;
            byte devType = obj.sontype;
            int devNo = obj.DevNo;
            string Dcode = obj.sCode;

            List<ObjKGL> KGL_ValueList = new List<ObjKGL>();
            KGL_Table tb = new KGL_Table();
            tb.Read_KGL_ValueList(stime, etime);
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                if (tb.Ready_KGL_ValueList)
                {
                    KGL_ValueList = Clone(tb.KGL_ValueList) as List<ObjKGL>;
                    break;
                }
                else Thread.Sleep(300);
            }

            List<ObjKGL> t1 = new List<ObjKGL>();   //回溯时间段前的数据
            List<ObjKGL> t2 = new List<ObjKGL>();   //回溯时间段的数据
            List<ObjKGL> t3 = new List<ObjKGL>();   //回溯时间段后的数据

            foreach (ObjKGL k in KGL_ValueList)
            {
                if (k.u_time < stime)
                {
                    t1.Add(k);
                }
                else if (k.u_time > etime)
                {
                    t3.Add(k);
                }
                else
                {
                    t2.Add(k);
                }
            }
            List<ObjKGL> t4 = new List<ObjKGL>();   //回溯时间段第1段数据
            List<ObjKGL> t5 = new List<ObjKGL>();   //回溯时间段第2段数据
            foreach (ObjKGL k in t2)
            {
                if (t4.Exists(x => x.u_time == k.u_time)) t5.Add(k);
                else t4.Add(k);
                //if (t4.Contains(k)) t5.Add(k);
                //else t4.Add(k);
            }
            List<ObjKGL> t6 = new List<ObjKGL>();   //需要发送的原始数据
            t6.AddRange(t1);
            if (recallnum == 1) t6.AddRange(t4);
            else t6.AddRange(t5);
            t6.AddRange(t3);
            
            //以下组织数据
            List<byte> sendBuf = TidyKglReplayData(t6, true, stime, etime);
            c_NetCom.RetSendKGLReplayData(Dcode, sendBuf);
        }
        /// <summary>
        /// 终端处理接收到的开关量回放数据。
        /// </summary>
        private static void tDisposeRevKglReplayData()
        {            
            byte[] t = TerminalReplayKglValue.ToArray();
            int m = 1;
            int stime = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
            m += 4;
            TerminalReplayKglValueTidy.stime = stime;
            int etime = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
            m += 4;
            TerminalReplayKglValueTidy.etime = etime;
            int allR = t[m] + (t[m + 1] << 8);
            m += 2;
            TerminalReplayKglValueTidy.AllRecordNum = allR;
            TerminalReplayKglValueTidy.KGLNum = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
            m += 4;
            TerminalReplayKglValueTidy.wholeKGLRecordNum = t[m] + (t[m + 1] << 8) + (t[m + 2] << 16);
            m += 2;
            ///以下是索引数据
            m += TerminalReplayKglValueTidy.wholeKGLRecordNum * 4;  //不处理索引
            ///以下是实际的数据
            objRevKGL tk = new objRevKGL();
            objRevKGL tkclone = new objRevKGL();    //保持上次接收到的全体开关量
            while (m < t.Length)
            {                
                byte flag = t[m++];     //类型
                if (flag == 1)   //全体开关量
                {
                    tk = new objRevKGL();
                    tk.AllFlag = true;
                    tk.kglNum = t[m] + (t[m + 1] << 8);
                    m += 2;
                    tk.time = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
                    m += 4;
                    int len = tk.kglNum / 8;
                    if (tk.kglNum % 8 != 0) len++;  //全体开关量的字节数
                    Array.Copy(t, m, tk.Value.ToArray(), 0, len);
                    m += len;
                    TerminalReplayKglValueTidy.KGL_ValueList.Add(tk);
                    tkclone = new objRevKGL();
                    tkclone = Clone(tk) as objRevKGL;   //复制数据到,用于下一包变化数据的基准数据
                }
                else   //变化开关量  ,填充到上次收到的全体开关量数据中.
                {                    
                    m++;    //变化开关量
                    tkclone.time = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
                    m += 4; //时间
                    int v = t[m] + (t[m + 1] << 8);
                    m += 2;
                    int vn = v & 0x7ffff;   //变化开关量序号
                    byte s = (byte)(v >> 15);  //变化开关量的值
                    int B = vn / 8;     //字节数
                    int b = vn % 8;     //字节所在的位

                    if (B < tkclone.Value.Count)
                    {
                        byte vv = tkclone.Value[B];
                        vv = (byte)(vv & (s << b));
                        vv = (byte)(vv | (s << b));
                        tkclone.Value[B] = vv;
                    }
                    TerminalReplayKglValueTidy.KGL_ValueList.Add(tkclone);
                    tk = new objRevKGL();
                    tk = Clone(tkclone) as objRevKGL;
                    tkclone = new objRevKGL();
                    tkclone = Clone(tk) as objRevKGL;   //从新复制一份新的全体数据.
                }
            }
        }
        #region 终端处理模拟量回放数据
        struct AIstruct       //类型描述结构
        {
            public int type;    //模拟量类型
            public int StartNo; //开始路号
        }

        struct Vstruct          //分记录结构
        {
            public int otime;   //时间偏移值
            public int value;   //值
        }

        class Rsturct          //一条记录结构
        {
            public int LuNo;    //路号
            public List<Vstruct> FjlSet = new List<Vstruct>(); //分记录集合
        }
        /// <summary>
        /// 终端处理模拟量回放数据
        /// </summary>
        /// <param name="reflag"></param>
        /// <param name="stime"></param>
        private static void TerminalDisposeReplayAnalogValue(byte reflag,int stime)
        {            
            byte[] buf = TerminalReplayAnalogValue.ToArray();
            int m = 0;
            int sstime = buf[m] + (buf[m + 1] << 8) + (buf[m + 2] << 16) + (buf[m + 3] << 24);
            m += 4;
            int AnalogTypeNum = buf[m] + (buf[m + 1] << 8);   //模拟量类型数
            m += 2;
            List<AIstruct> AnalogTypeSet = new List<AIstruct>();
            for (int i = 0; i < AnalogTypeNum; i++)         //处理模拟量类型描述
            {
                AIstruct ai = new AIstruct();
                ai.type = buf[m] + (buf[m + 1] << 8);   //模拟量类型
                m += 2;
                ai.StartNo = buf[m] + (buf[m + 1] << 8) + (buf[m + 2] << 16) + (buf[m + 3] << 24);
                m += 4;
            }
            int recordNum = buf[m] + (buf[m + 1] << 8);   //记录数
            m += 2;
            List<Rsturct> RecordList = new List<Rsturct>();
            for (int i = 0; i < recordNum; i++)
            {
                Rsturct rs = new Rsturct();
                rs.LuNo = buf[m] + (buf[m + 1] << 8);    //路号
                m += 2;
                int fjls = buf[m] + (buf[m + 1] << 8);    //分记录数
                m += 2;
                
                for (int j = 0; j < fjls; j++)
                {
                    Vstruct fjl = new Vstruct();
                    fjl.otime = 0;
                    if (reflag == 0x42)
                    {
                        fjl.otime = buf[m] + (buf[m + 1] << 8) + (buf[m + 2] << 16) + (buf[m + 3] << 24);
                        m += 4;
                    }
                    else
                    {
                        fjl.otime = buf[m] + (buf[m + 1] << 8);
                        m += 2;
                    }
                    fjl.value = buf[m] + (buf[m + 1] << 8);
                    m += 2;
                    rs.FjlSet.Add(fjl);
                }
                RecordList.Add(rs);
            }
            //解析后的数据要按模拟量类型存入缓冲区
            TerminalReplayAnalogValueTidy.Clear();
            List<ReplayClass> liset = new List<ReplayClass>();
            byte OldAnalogType = 0; //老的模拟量类型
            //foreach (Rsturct k in RecordList)
            for (int s = 0; s < RecordList.Count; s++)
            {
                Rsturct k = RecordList[s];
                //依据路号获得模拟量的类型和序号                
                byte AnalogType = 0;
                int AnalogStartNo = 0;
                for (int i = 0; i < AnalogTypeSet.Count; i++)
                {
                    if (k.LuNo < AnalogTypeSet[i].StartNo)
                    {
                        if (k.LuNo >= AnalogTypeSet[i - 1].StartNo)
                        {
                            AnalogType = (byte)AnalogTypeSet[i - 1].type;
                            AnalogStartNo = AnalogTypeSet[i - 1].StartNo;
                        }
                        else
                        {
                            Console.WriteLine("模拟量类型的路号没有按顺序传送");
                        }
                        break;
                    }
                    else if (i == (AnalogTypeSet.Count - 1))    //最后一种模拟量类型
                    {
                        AnalogType = (byte)AnalogTypeSet[i].type;
                        AnalogStartNo = AnalogTypeSet[i].StartNo;
                        break;
                    }
                }
                if (OldAnalogType != AnalogType)    //换了一种模拟量类型
                {
                    if (OldAnalogType != 0)
                    {
                        TerminalReplayAnalogValueTidy.Add((AnalogCodeType)OldAnalogType, liset);    //一种模拟量类型数据组织完成
                    }
                    OldAnalogType = AnalogType;
                    liset = new List<ReplayClass>();    //重新开辟一个新的空间
                }

                int analogNo = k.LuNo - AnalogStartNo + 1;  //模拟量序号是从1开始的
                string AnalogTypeName = c_Device.GetAnalogTypeName((AnalogCodeType)AnalogType);

                ReplayClass li = new ReplayClass();
                li.AnalogNo = analogNo;
                string IniFile = c_Device.GetIniFileFromAnalogTypeName(AnalogTypeName);
                li.objSet = c_Device.GetSingleAnalogConfig_Inf(IniFile, analogNo, AnalogTypeName);
                for (int i = 0; i < k.FjlSet.Count; i++)
                {
                    objTimeValue ttv = new objTimeValue();
                    ttv.u_time = k.FjlSet[i].otime + sstime;  //时间=偏移量加时间
                    ttv.Dvalue = (short)k.FjlSet[i].value;
                    ttv.Tvalue = c_RealTimeValue.ConvertAnalogValue(AnalogTypeName, ttv.Dvalue);
                    li.ValueList.Add(ttv);
                }
                liset.Add(li);  //加入到列表中
                if (s == RecordList.Count - 1)    //判断到最后一个，最后一种模拟量类型加入缓冲区
                {
                    TerminalReplayAnalogValueTidy.Add((AnalogCodeType)OldAnalogType, liset);
                    break;
                }
            }
        }
        #endregion
        /// <summary>
        /// 组织模拟量回放压缩包数据
        /// </summary>
        /// <param name="li"></param>
        /// <param name="stime"></param>
        /// <returns></returns>
        private static List<byte> TidyAnalogReplayUnpressData(Dictionary<AnalogCodeType, List<ReplayClass>> li, int stime, bool recall)
        {
            List<byte> ti = new List<byte>();
            byte[] m = new byte[4];
            m = BitConverter.GetBytes(stime);
            ti.AddRange(m);                     //时间
            int typeNum = li.Count;
            m = new byte[2];
            m = BitConverter.GetBytes(typeNum);
            ti.AddRange(m);                     //模拟量类型数
            int startNo = 0;
            foreach (AnalogCodeType key in li.Keys) //填充模拟量信息描述
            {
                byte type = (byte)key;
                ti.Add(type);
                ti.Add(0);
                ti.Add((byte)(startNo & 0xff));
                ti.Add((byte)((startNo >> 8) & 0xff));
                //要获取模拟量类型的模拟量个数
                startNo += c_Device.GetAnalogTypeDevNum(type); //此种类型下的设备数量.                
            }
            //------------记录数，为所有的模拟量个数，次数表现为startNo
            ti.Add((byte)(startNo & 0xff));
            ti.Add((byte)((startNo >> 8) & 0xff));
            //填实际记录
            int luNo = 0;       //路号，统一编号.
            foreach (AnalogCodeType key in li.Keys)
            {
                int AnalogNum = c_Device.GetAnalogTypeDevNum((byte)key);    //此种模拟量类型的个数
                for (int i = 0; i < AnalogNum; i++)     //该种类型的设备数目
                {
                    ti.Add((byte)(luNo & 0xff));
                    ti.Add((byte)((luNo >> 8) & 0xff));
                    luNo++; //路号统一编号
                    int fjls = 0;       //分记录数
                    bool bfjls = false;
                    foreach (ReplayClass rc in li[key])
                    {
                        if (rc.AnalogNo == i + 1)   //序号是从1开始的
                        {
                            bfjls = true;           //分记录数填写记录
                            fjls = rc.ValueList.Count;      //填分记录数
                            ti.Add((byte)(fjls & 0xff));
                            ti.Add((byte)((fjls >> 8) & 0xff));
                            int sstime = 0;
                            for (int j = 0; j < rc.ValueList.Count; j++)
                            {
                                sstime = rc.ValueList[j].u_time;
                                int offtime = 0;
                                if (j == 0) offtime = 0;
                                else
                                {
                                    offtime = sstime - stime;   //时间偏移量
                                }
                                if (recall)
                                {
                                    byte[] tt = new byte[4];
                                    tt = BitConverter.GetBytes(offtime);
                                    ti.AddRange(tt);
                                }
                                else
                                {
                                    byte[] tt = new byte[2];
                                    tt = BitConverter.GetBytes(offtime);
                                    ti.AddRange(tt);
                                }
                                byte[] vt = new byte[2];
                                vt = BitConverter.GetBytes(rc.ValueList[j].Dvalue);
                                ti.AddRange(vt);
                            }
                            break;      //找到了模拟量序号
                        }
                    }
                    if (bfjls == false)
                    {
                        //填写分记录数为0的模拟量
                        ti.Add((byte)(fjls & 0xff));
                        ti.Add((byte)((fjls >> 8) & 0xff));
                    }
                }
            }
            return ti;
        }

        /// <summary>
        /// 站机提取模拟量回放数据
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetAnalogData(object o)
        {
            objNetAnalogReplay obj = (objNetAnalogReplay)o;
            int stime = obj.stime;
            int etime = obj.etime;
            string Dcode = obj.sCode;
            int anlogNum = obj.analogNum;
            List<byte> analogSet = new List<byte>(obj.AnalogSet);
            AnalogTable tb = new AnalogTable();
            if (anlogNum == 0xff)
            {
                tb.ReadReplayValue(stime, etime);
            }
            else tb.ReadReplayValue(stime, etime, analogSet);

            Dictionary<AnalogCodeType, List<ReplayClass>> ReplayValueList = new Dictionary<AnalogCodeType, List<ReplayClass>>();
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                else if (tb.Ready_ReplayValueList)
                {
                    ReplayValueList = Clone(tb.ReplayValueList) as Dictionary<AnalogCodeType, List<ReplayClass>>;
                }
                else
                {
                    Thread.Sleep(300);
                }
            }
            //组织数据
            List<byte> UnBuf = TidyAnalogReplayUnpressData(ReplayValueList, stime, false);

            c_NetCom.RetSendAnalogReplayData(Dcode, 0x41, stime, UnBuf);            
        }
        /// <summary>
        /// 站机提取模拟量回放数据，时间回溯段
        /// </summary>
        /// <param name="o"></param>
        private static void zDisposeGetAnalogRecallData(object o)
        {
            objNetAnalogReplay obj = (objNetAnalogReplay)o;
            int stime = obj.stime;
            int etime = obj.etime;
            int rsNum = obj.recallNum;
            int rstime = obj.recallstime;
            int retime = obj.recalletime;
            string Dcode = obj.sCode;
            AnalogTable tb = new AnalogTable();
            
            tb.ReadReplayValue(stime, etime);           

            Dictionary<AnalogCodeType, List<ReplayClass>> ReplayValueList = new Dictionary<AnalogCodeType, List<ReplayClass>>();
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                else if (tb.Ready_ReplayValueList)
                {
                    ReplayValueList = Clone(tb.ReplayValueList) as Dictionary<AnalogCodeType, List<ReplayClass>>;
                }
                else
                {
                    Thread.Sleep(300);
                }
            }
            //挑选数据
            Dictionary<AnalogCodeType, List<ReplayClass>> ts = new Dictionary<AnalogCodeType, List<ReplayClass>>();  //挑选后的缓冲区
            
            foreach (AnalogCodeType key in ReplayValueList.Keys)
            {
                List<ReplayClass> tsReplay = new List<ReplayClass>();
                foreach (ReplayClass u in ReplayValueList[key])
                {
                    ReplayClass tsu = new ReplayClass();
                    tsu.AnalogNo = u.AnalogNo;
                    tsu.objSet =Clone( u.objSet) as objSingleAnalogStruct;
                    
                    List<objTimeValue> t1 = new List<objTimeValue>();   //回溯时间前数据
                    List<objTimeValue> t2 = new List<objTimeValue>();   //回溯时间段数据
                    List<objTimeValue> t3 = new List<objTimeValue>();   //回溯时间后数据
                    List<objTimeValue> t4 = new List<objTimeValue>();   //回溯第一段数据
                    List<objTimeValue> t5 = new List<objTimeValue>();   //回溯第二段数据
                    List<objTimeValue> t6 = new List<objTimeValue>();   //最后的数据，依据用户选择的组织的数据
                    for (int i = 0; i < u.ValueList.Count; i++)
                    {
                        if (u.ValueList[i].u_time < rstime)
                        {
                            t1.Add(u.ValueList[i]);
                        }
                        else if (u.ValueList[i].u_time > retime)
                        {
                            t3.Add(u.ValueList[i]);
                        }
                        else
                        {
                            t2.Add(u.ValueList[i]);
                        }                        
                    }

                    //t2再分解                        
                    for (int j = 0; j < t2.Count; j++)
                    {
                        if (t4.Exists(x => x.u_time == t2[j].u_time)) t5.Add(t2[j]);
                        else t4.Add(t2[j]);                        
                    }

                    t6.AddRange(t1);
                    if (rsNum == 1) t6.AddRange(t4);
                    else t6.AddRange(t5);
                    t6.AddRange(t3);    //回溯时间段后面的数据
                    tsu.ValueList = t6;     //传地址
                    tsReplay.Add(tsu);
                }
                ts.Add(key, tsReplay);
            }
            //组织数据
            List<byte> UnBuf = TidyAnalogReplayUnpressData(ts, stime, true);
            c_NetCom.RetSendAnalogReplayData(Dcode, 0x42, stime, UnBuf);
        }

        private static List<byte> TidyHighFrequencyReplayUnpressData(Dictionary<AnalogCodeType, List<HighReplayClass>> li, int stime, bool recall)
        {
            List<byte> ti = new List<byte>();
            byte[] m = new byte[4];
            m = BitConverter.GetBytes(stime);
            ti.AddRange(m);                     //时间
            int typeNum = li.Count;
            m = new byte[2];
            m = BitConverter.GetBytes(typeNum);
            ti.AddRange(m);                     //模拟量类型数
            int startNo = 0;
            foreach (AnalogCodeType key in li.Keys) //填充模拟量信息描述
            {
                byte type = (byte)key;
                ti.Add(type);
                ti.Add(0);
                ti.Add((byte)(startNo & 0xff));
                ti.Add((byte)((startNo >> 8) & 0xff));
                int CJfre = c_Device.GetHighFrequencyDotNum(type);  //得到采集频率
                ti.Add((byte)(CJfre & 0xff));
                ti.Add((byte)((CJfre >> 8) & 0xff));
                //要获取模拟量类型的模拟量个数
                startNo += c_Device.GetAnalogTypeDevNum(type); //此种类型下的设备数量.                
            }
            //------------记录数，为所有的模拟量个数，次数表现为startNo
            ti.Add((byte)(startNo & 0xff));
            ti.Add((byte)((startNo >> 8) & 0xff));
            //填实际记录
            int luNo = 0;       //路号，统一编号.
            foreach (AnalogCodeType key in li.Keys)
            {
                int CJfre = c_Device.GetHighFrequencyDotNum((byte)key);     //采集频率
                int AnalogNum = c_Device.GetAnalogTypeDevNum((byte)key);    //此种模拟量类型的个数
                for (int i = 0; i < AnalogNum; i++)     //该种类型的设备数目
                {
                    ti.Add((byte)(luNo & 0xff));
                    ti.Add((byte)((luNo >> 8) & 0xff));
                    luNo++; //路号统一编号
                    int fjls = 0;       //分记录数
                    bool bfjls = false;
                    foreach (HighReplayClass rc in li[key])
                    {                        
                        if (rc.AnalogNo == i + 1)   //序号是从1开始的
                        {
                            bfjls = true;           //分记录数填写记录
                            fjls = 0;      //填分记录数
                            for (int j = 0; j < rc.ValueList.Count; j++)
                            {
                                fjls += rc.ValueList[j].SecondValueList.Count;      //每秒都有采集频率个数据，目前只有半自闭，应该=10
                                
                                if (rc.ValueList[j].SecondValueList.Count != CJfre)
                                {
                                    Console.WriteLine("采集频率和每秒的个数不一致");
                                    return null;
                                }
                            }
                            
                            ti.Add((byte)(fjls & 0xff));
                            ti.Add((byte)((fjls >> 8) & 0xff));
                            int sstime = 0;
                            for (int j = 0; j < rc.ValueList.Count; j++)
                            {
                                sstime = rc.ValueList[j].utime;
                                int offtime = 0;
                                if (j == 0) offtime = 0;
                                else
                                {
                                    offtime = sstime - stime;   //时间偏移量
                                }
                                byte[] ttr = new byte[4];
                                byte[] tt = new byte[2];
                                if (recall)
                                {                                    
                                    ttr = BitConverter.GetBytes(offtime);                                    
                                }
                                else
                                {                                    
                                    tt = BitConverter.GetBytes(offtime);
                                }
                                foreach (objHigFre k in rc.ValueList[j].SecondValueList)
                                {
                                    if (recall) ti.AddRange(ttr);   //时间偏移，回溯的为4个字节
                                    else ti.AddRange(tt);           //时间偏移，不回溯的为2字节
                                    byte[] vt = new byte[2];
                                    vt = BitConverter.GetBytes(k.wValue);
                                    ti.AddRange(vt);
                                }                                
                            }
                            break;      //找到了模拟量序号
                        }
                    }
                    if (bfjls == false)
                    {
                        //填写分记录数为0的模拟量
                        ti.Add((byte)(fjls & 0xff));
                        ti.Add((byte)((fjls >> 8) & 0xff));
                    }
                }
            }
            return ti;
        }
        /// <summary>
        /// 站机提取高频回放数据
        /// </summary>
        /// <param name="o"></param>
        static private void zDisposeGetHighFrequencyReplayData(object o)
        {
            objNetAnalogReplay obj = (objNetAnalogReplay)o;
            int stime = obj.stime;
            int etime = obj.etime;
            string Dcode = obj.sCode;
            int anlogNum = obj.analogNum;
            List<byte> analogSet = new List<byte>(obj.AnalogSet);
            AnalogHigFreTable tb = new AnalogHigFreTable();
            if (anlogNum == 0xff)
            {
                tb.ReadReplayValue(stime, etime);
            }
            else tb.ReadReplayValue(stime, etime, analogSet);
            Dictionary<AnalogCodeType, List<HighReplayClass>> ReplayValueList = new Dictionary<AnalogCodeType, List<HighReplayClass>>();
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                else if (tb.Ready_ReplayValueList)
                {
                    ReplayValueList = Clone(tb.ReplayValueList) as Dictionary<AnalogCodeType, List<HighReplayClass>>;
                    break;
                }
                else Thread.Sleep(300);
            }
            //组织数据
            List<byte> UnBuf = TidyHighFrequencyReplayUnpressData(ReplayValueList, stime, false);
            c_NetCom.RetSendHighFrequencyReplayData(Dcode, 0x41, stime, UnBuf);
        }
        /// <summary>
        /// 提取站机高频回放数据 回溯时间段
        /// </summary>
        /// <param name="o"></param>
        static private void zDisposeGetHighFrequencyReplayRecallData(object o)
        {
            objNetAnalogReplay obj = (objNetAnalogReplay)o;
            int stime = obj.stime;
            int etime = obj.etime;
            int rsNum = obj.recallNum;
            int rstime = obj.recallstime;
            int retime = obj.recalletime;
            string Dcode = obj.sCode;
            AnalogHigFreTable tb = new AnalogHigFreTable();
            tb.ReadReplayValue(stime, etime);
            Dictionary<AnalogCodeType, List<HighReplayClass>> ReplayValueList = new Dictionary<AnalogCodeType, List<HighReplayClass>>();
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                else if (tb.Ready_ReplayValueList)
                {
                    ReplayValueList = Clone(tb.ReplayValueList) as Dictionary<AnalogCodeType, List<HighReplayClass>>;
                    break;
                }
                else Thread.Sleep(300);
            }
            //挑选数据
            //挑选后的缓冲区.
            Dictionary<AnalogCodeType, List<HighReplayClass>> ts = new Dictionary<AnalogCodeType, List<HighReplayClass>>();
            foreach (AnalogCodeType key in ReplayValueList.Keys)
            {
                List<HighReplayClass> tsReplay = new List<HighReplayClass>();
                foreach (HighReplayClass u in ReplayValueList[key])
                {
                    HighReplayClass hrc = new HighReplayClass();
                    hrc.AnalogNo = u.AnalogNo;
                    hrc.objSet = Clone(u.objSet) as objSingleAnalogStruct;
                    List<HigFreAnalogValue> ylist = new List<HigFreAnalogValue>(); //用户最终选择的数据
                    List<HigFreAnalogValue> t1 = new List<HigFreAnalogValue>(); //回溯时间段前的数据
                    List<HigFreAnalogValue> t2 = new List<HigFreAnalogValue>(); //回溯时间段的数据
                    List<HigFreAnalogValue> t3 = new List<HigFreAnalogValue>(); //回溯时间段后的数据
                    List<HigFreAnalogValue> t4 = new List<HigFreAnalogValue>(); //回溯第一段数据
                    List<HigFreAnalogValue> t5 = new List<HigFreAnalogValue>(); //回溯第二段数据
                    foreach (HigFreAnalogValue y in hrc.ValueList)
                    {
                        if (y.utime < rstime)
                        {
                            t1.Add(y);
                        }
                        else if (y.utime > retime)
                        {
                            t3.Add(y);
                        }
                        else
                        {
                            t2.Add(y);
                        }
                    }
                    foreach (HigFreAnalogValue y in t2)
                    {
                        int utime = y.utime;
                        if (t4.Exists(x=>x.utime==utime)) t5.Add(y);
                        else t4.Add(y);
                    }
                    ylist.AddRange(t1);
                    if (rsNum == 1) ylist.AddRange(t4);
                    else ylist.AddRange(t5);
                    ylist.AddRange(t3);
                    hrc.ValueList = ylist;
                    tsReplay.Add(hrc);
                }
                ts.Add(key, tsReplay);
            }
            //组织数据
            List<byte> UnBuf = TidyHighFrequencyReplayUnpressData(ts, stime, false);
            c_NetCom.RetSendHighFrequencyReplayData(Dcode, 0x42, stime, UnBuf);
        }

        #region 终端解析高频模拟量回放数据
        struct Histruct //高频回放信息描述
        {
           public int type;   //类型
           public int StartNo;//开始路号
           public int Fre;    //采集频率
        }

        class HVstruct                  //分记录结构
        {
            public int otime = 0;                       //时间偏移值
            public List<int> value = new List<int>();   //值
        }

        class HRsturct          //一条记录结构
        {
            public int LuNo = 0;    //路号
            public List<HVstruct> FjlSet = new List<HVstruct>(); //分记录集合
        }
        /// <summary>
        /// 终端组织高频模拟量回放数据
        /// </summary>
        /// <param name="rflag"></param>
        /// <param name="stime"></param>
        private static void TerminalDisposeReplayHighFrequencyValue(byte rflag,int stime)
        {
            byte[] buf = TerminalReplayHighFrequencyValue.ToArray();
            int m = 0;
            int sstime = buf[m] + (buf[m + 1] << 8) + (buf[m + 2] << 16) + (buf[m + 3] << 24);
            m += 4;
            int AnalogTypeNum = buf[m] + (buf[m + 1] << 8);   //模拟量类型数
            m += 2;
            List<Histruct> AnalogTypeSet = new List<Histruct>();
            for (int i = 0; i < AnalogTypeNum; i++)         //处理模拟量类型描述
            {
                Histruct ai = new Histruct();
                ai.type = buf[m] + (buf[m + 1] << 8);   //模拟量类型
                m += 2;
                ai.StartNo = buf[m] + (buf[m + 1] << 8) + (buf[m + 2] << 16) + (buf[m + 3] << 24);
                m += 4;
                ai.Fre = buf[m] + (buf[m + 1] << 8);  //采集频率
                m += 2;
            }
            int recordNum = buf[m] + (buf[m + 1] << 8);   //记录数
            m += 2;
            List<HRsturct> RecordList = new List<HRsturct>();
            for (int i = 0; i < recordNum; i++)
            {
                HRsturct rs = new HRsturct();
                rs.LuNo = buf[m] + (buf[m + 1] << 8);    //路号
                m += 2;
                int fjls = buf[m] + (buf[m + 1] << 8);    //分记录数
                m += 2;
                ///首先要获取该种模拟量的采集频率
                int AnalogFre = 0;
                if (AnalogTypeNum == 1)
                {
                    AnalogFre = AnalogTypeSet[0].Fre;
                }
                else
                {
                    for (int x = 0; x < AnalogTypeNum - 1; x++)
                    {
                        if (rs.LuNo >= AnalogTypeSet[x].StartNo && rs.LuNo < AnalogTypeSet[x + 1].StartNo)
                        {
                            AnalogFre = AnalogTypeSet[x].Fre;
                        }
                    }
                }
                if (AnalogFre == 0)
                {
                    Console.WriteLine("高频模拟量回放采集错误");
                    return;
                }
                //------------------------
                for (int j = 0; j < fjls;)      //分记录数
                {
                    HVstruct fjl = new HVstruct();
                    int time = -1;
                    for (int x = 0; x < AnalogFre; x++)     //应该是采集频率个相同的数据,每秒应该有采集频率数的数据
                    {
                        int ttime = 0;
                        if (rflag == 0x42)
                        {
                            ttime = buf[m] + (buf[m + 1] << 8) + (buf[m + 2] << 16) + (buf[m + 3] << 24);
                            m += 4;
                        }
                        else
                        {
                            ttime = buf[m] + (buf[m + 1] << 8);
                            m += 2;
                        }
                        if (time == -1)
                        {
                            time = ttime;
                            fjl.otime = time;
                        }
                        else if (time != ttime)
                        {
                            Console.WriteLine("高频模拟量采集频率错误");
                            return;
                        }
                        
                        int v = buf[m] + (buf[m + 1] << 8);
                        m += 2;
                        fjl.value.Add(v);
                        j++;
                    }
                    rs.FjlSet.Add(fjl);
                }
                RecordList.Add(rs);
            }
            //解析后的数据要按模拟量类型存入缓冲区
            TerminalReplayHighFrequencyValueTidy.Clear();
            List<HighReplayClass> liset = new List<HighReplayClass>();
            byte OldAnalogType = 0; //老的模拟量类型
            //foreach (Rsturct k in RecordList)
            for (int s = 0; s < RecordList.Count; s++)
            {
                HRsturct k = RecordList[s];
                //依据路号获得模拟量的类型和序号
                byte AnalogType = 0;
                int AnalogStartNo = 0;
                for (int i = 0; i < AnalogTypeSet.Count; i++)
                {
                    if (k.LuNo < AnalogTypeSet[i].StartNo)
                    {
                        if (k.LuNo >= AnalogTypeSet[i - 1].StartNo)
                        {
                            AnalogType = (byte)AnalogTypeSet[i - 1].type;
                            AnalogStartNo = AnalogTypeSet[i - 1].StartNo;
                        }
                        else
                        {
                            Console.WriteLine("模拟量类型的路号没有按顺序传送");
                        }
                        break;
                    }
                    else if (i == (AnalogTypeSet.Count - 1))    //最后一种模拟量类型
                    {
                        AnalogType = (byte)AnalogTypeSet[i].type;
                        AnalogStartNo = AnalogTypeSet[i].StartNo;
                        break;
                    }
                }
                if (OldAnalogType != AnalogType)    //换了一种模拟量类型
                {
                    if (OldAnalogType != 0)
                    {

                        TerminalReplayHighFrequencyValueTidy.Add((AnalogCodeType)OldAnalogType, liset);    //一种模拟量类型数据组织完成
                    }
                    OldAnalogType = AnalogType;
                    liset = new List<HighReplayClass>();    //重新开辟一个新的空间
                }

                int analogNo = k.LuNo - AnalogStartNo + 1;  //模拟量序号是从1开始的
                string AnalogTypeName = c_Device.GetAnalogTypeName((AnalogCodeType)AnalogType);

                HighReplayClass li = new HighReplayClass();
                li.AnalogNo = analogNo;
                string IniFile = c_Device.GetIniFileFromAnalogTypeName(AnalogTypeName);
                li.objSet = c_Device.GetSingleAnalogConfig_Inf(IniFile, analogNo, AnalogTypeName);
                for (int i = 0; i < k.FjlSet.Count; i++)
                {
                    HigFreAnalogValue liv = new HigFreAnalogValue();
                    liv.utime = k.FjlSet[i].otime+ sstime;      //时间需要加上偏移量
                    //List<objHigFre> yk = new List<objHigFre>();
                    for(int y=0;y<k.FjlSet[i].value.Count;y++)
                    {
                        objHigFre yy = new objHigFre();
                        yy.wValue = (Int16)k.FjlSet[i].value[y];
                        yy.fValue = c_RealTimeValue.ConvertAnalogValue(AnalogTypeName, (short)k.FjlSet[i].value[y]);
                        liv.SecondValueList.Add(yy);
                    }
                    
                    li.ValueList.Add(liv);
                }
                liset.Add(li);  //加入到列表中
                if (s == RecordList.Count - 1)    //判断到最后一个，最后一种模拟量类型加入缓冲区
                {
                    TerminalReplayHighFrequencyValueTidy.Add((AnalogCodeType)OldAnalogType, liset);
                    break;
                }
            }
        }
        #endregion
        /// <summary>
        /// 站机处理提取开关量历史数据命令
        /// </summary>
        /// <param name="o"></param>
        static private void DisposeGetKglHistoryData(object o)
        {
            objNetCode obj = (objNetCode)o;
            int stime = obj.stime;
            int etime = obj.etime;
            string Dcode = obj.sCode;

            List<ObjKGL> KGL_ValueList = new List<ObjKGL>();
            KGL_Table tb = new KGL_Table();
            tb.Read_KGL_ValueList(stime, etime);
            while (true)
            {
                if (tb.ErrorFlag != 0) break;
                if (tb.Ready_KGL_ValueList)
                {
                    KGL_ValueList = Clone(tb.KGL_ValueList) as List<ObjKGL>;
                    break;
                }
                else Thread.Sleep(300);
            }
            //以下组织数据
            List<byte> sendBuf = TidyKglReplayData(KGL_ValueList, false, stime, etime);
            c_NetCom.RetSendKglData(Dcode, sendBuf);
        }
        /// <summary>
        /// 终端处理开关量历史数据
        /// </summary>
        static private void tDisposeRevKglHistoryData()
        {
            byte[] t = TerminalHistoryKglValue.ToArray();
            int m = 0;
            int stime = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
            m += 4;
            TerminalHistoryKglValueTidy.stime = stime;
            int etime = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
            m += 4;
            TerminalHistoryKglValueTidy.etime = etime;
            int allR = t[m] + (t[m + 1] << 8);
            m += 2;
            TerminalHistoryKglValueTidy.AllRecordNum = allR;
            TerminalHistoryKglValueTidy.KGLNum = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
            m += 4;
            TerminalHistoryKglValueTidy.wholeKGLRecordNum = t[m] + (t[m + 1] << 8) + (t[m + 2] << 16);
            m += 2;
            ///以下是索引数据
            m += TerminalHistoryKglValueTidy.wholeKGLRecordNum * 4;  //不处理索引
            ///以下是实际的数据
            objRevKGL tk = new objRevKGL();
            objRevKGL tkclone = new objRevKGL();    //保持上次接收到的全体开关量
            while (m < t.Length)
            {
                byte flag = t[m++];     //类型
                if (flag == 1)   //全体开关量
                {
                    tk = new objRevKGL();
                    tk.AllFlag = true;
                    tk.kglNum = t[m] + (t[m + 1] << 8);
                    m += 2;
                    tk.time = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
                    m += 4;
                    int len = tk.kglNum / 8;
                    if (tk.kglNum % 8 != 0) len++;  //全体开关量的字节数
                    Array.Copy(t, m, tk.Value.ToArray(), 0, len);
                    m += len;
                    TerminalHistoryKglValueTidy.KGL_ValueList.Add(tk);
                    tkclone = new objRevKGL();
                    tkclone = Clone(tk) as objRevKGL;   //复制数据到,用于下一包变化数据的基准数据
                }
                else   //变化开关量  ,填充到上次收到的全体开关量数据中.
                {
                    m++;    //变化开关量
                    tkclone.time = t[m] + (t[m + 1] << 8) +( t[m + 2] << 16) + (t[m + 3] << 24);
                    m += 4; //时间
                    int v = t[m] + (t[m + 1] << 8);
                    m += 2;
                    int vn = v & 0x7ffff;   //变化开关量序号
                    byte s = (byte)(v >> 15);  //变化开关量的值
                    int B = vn / 8;     //字节数
                    int b = vn % 8;     //字节所在的位

                    if (B < tkclone.Value.Count)
                    {
                        byte vv = tkclone.Value[B];
                        vv = (byte)(vv & (s << b));
                        vv = (byte)(vv | (s << b));
                        tkclone.Value[B] = vv;
                    }
                    TerminalHistoryKglValueTidy.KGL_ValueList.Add(tkclone);
                    tk = new objRevKGL();
                    tk = Clone(tkclone) as objRevKGL;
                    tkclone = new objRevKGL();
                    tkclone = Clone(tk) as objRevKGL;   //从新复制一份新的全体数据.
                }
            }
        }
        /// <summary>
        /// 站机处理记录曲线时间命令
        /// </summary>
        /// <param name="o"></param>
        static private void zDisposeGetRecordCurveTimeList(object o)
        {
            objNetCode ok = (objNetCode)o;
            string Dcode = ok.sCode;
            int CurveType = ok.sontype;
            int DevNo = ok.DevNo;
            if (CurveType == 0x10)  //道岔动作电流曲线
            {
                DcdlqxTable dt = new DcdlqxTable();
                string dname = c_Device.GetDcdlqxDevName(DevNo);
                dt.Read_DcdlqxTimeList(dname);
                List<int> li = new List<int>();
                while (true)
                {
                    if (dt.dlqxErrorFlag != 0) break;
                    else if (dt.Ready_DcdlqxValue)
                    {
                        foreach (DateTime t in dt.DcdlqxTimeList)
                        {
                            int u = (int)MySql.DateTimeToTime_t(t);
                            li.Add(u);
                        }
                    }
                    else Thread.Sleep(100);
                }
                c_NetCom.RetSendRecordCurveTime(Dcode, (byte)CurveType, li);
            }
            else if (CurveType == 0x13) //高压不对称
            {
                GybdcQxTable dt = new GybdcQxTable();
                string dname = c_Device.GetGybdcDyDevName(DevNo);
                dt.ReadTimeList(dname);
                List<int> li = new List<int>();
                while (true)
                {
                    if (dt.ErrorFlag != 0) break;
                    else if (dt.Ready_TimeList)
                    {
                        foreach (DateTime t in dt.TimeList)
                        {
                            int u = (int)MySql.DateTimeToTime_t(t);
                            li.Add(u);
                        }
                    }
                    else Thread.Sleep(100);
                }
                c_NetCom.RetSendRecordCurveTime(Dcode, (byte)CurveType, li);                    
            }
        }
        /// <summary>
        /// 道岔电流曲线数据加入发送缓冲区
        /// </summary>
        /// <param name="type"></param>
        /// <param name="li"></param>
        /// <param name="qx"></param>
        /// <param name="k"></param>
        static private void AddToRecordCurveTidyList(byte type,List<byte> li, ObjDcdlType qx, int k)
        {
            li.Add(type);  //类型
            li.Add((byte)qx.devNo);
            li.Add((byte)(qx.devNo >> 8));
            li.Add((byte)qx.u_time);
            li.Add((byte)(qx.u_time >> 8));
            li.Add((byte)(qx.u_time >> 16));
            li.Add((byte)(qx.u_time >> 24));
            li.Add((byte)qx.zh_order);
            li.Add((byte)qx.dotNumber);
            li.Add((byte)(qx.dotNumber >> 8));
            List<ObjRCurValue> obj = new List<ObjRCurValue>();
            if (k == 1) obj = qx.qxA;
            else if (k == 2) obj = qx.qxB;
            else if (k == 3) obj = qx.qxC;
            else if (k == 4) obj = qx.glqx;
            foreach (ObjRCurValue x in obj)
            {
                li.Add((byte)x.wValue);
                li.Add((byte)(x.wValue >> 8));                
            }
        }
        /// <summary>
        /// 整理需要发送的道岔电流曲线数据
        /// </summary>
        /// <param name="dlqx"></param>
        /// <param name="ckqx"></param>
        /// <param name="mcqx"></param>
        /// <param name="dlNum"></param>
        /// <param name="ckNum"></param>
        /// <param name="mcNum"></param>
        /// <returns></returns>
        static private List<byte> TidyRecordCurveData(ObjDcdlType dlqx, ObjDcdlType ckqx, ObjDcdlType mcqx, int dlNum, int ckNum, int mcNum)
        {
            List<byte> li = new List<byte>();
            if (dlNum == 1)
            {
                AddToRecordCurveTidyList(0, li, dlqx, 1);
            }
            else if (dlNum == 4)
            {
                AddToRecordCurveTidyList(0, li, dlqx, 1);
                AddToRecordCurveTidyList(0, li, dlqx, 2);
                AddToRecordCurveTidyList(0, li, dlqx, 3);
                AddToRecordCurveTidyList(3, li, dlqx, 4);
            }
            if (ckNum == 1)
            {
                AddToRecordCurveTidyList(2, li, ckqx, 1);
            }
            else if (ckNum == 4)
            {
                AddToRecordCurveTidyList(2, li, ckqx, 1);
                AddToRecordCurveTidyList(2, li, ckqx, 2);
                AddToRecordCurveTidyList(2, li, ckqx, 3);
                AddToRecordCurveTidyList(5, li, ckqx, 4);
            }
            if (mcNum == 1)
            {
                AddToRecordCurveTidyList(1, li, mcqx, 1);
            }
            else if (mcNum == 4)
            {
                AddToRecordCurveTidyList(1, li, mcqx, 1);
                AddToRecordCurveTidyList(1, li, mcqx, 2);
                AddToRecordCurveTidyList(1, li, mcqx, 3);
                AddToRecordCurveTidyList(4, li, mcqx, 4);
            }
            return li;
        }
        /// <summary>
        /// 整理要发送的高压不对称曲线数据
        /// </summary>
        /// <param name="gy"></param>
        /// <param name="li"></param>
        static private void TidyGybdcRecordCurveData(int time,int devNo,ObjGybdcType gy,List<byte>li)
        {
            li.Add((byte)(devNo));
            li.Add((byte)(devNo >> 8));
            li.Add((byte)time);
            li.Add((byte)(time >> 8));
            li.Add((byte)(time >> 16));
            li.Add((byte)(time >> 24));
            int csFre = 10000;
            li.Add((byte)csFre);
            li.Add((byte)(csFre >> 8));
            int bxs = 3;
            li.Add((byte)bxs);
            li.Add((byte)(bxs >> 8));
            //第一条曲线
            li.Add((byte)gy.start1);
            li.Add((byte)(gy.start1>>8));
            li.Add((byte)gy.dotnum1);
            li.Add((byte)(gy.dotnum1>>8));
            for (int i = 0; i < gy.dotnum1; i++)
            {
                li.Add((byte)gy.qx1[i].wValue);
                li.Add((byte)(gy.qx1[i].wValue >> 8));
            }
            //第二条曲线
            li.Add((byte)gy.start2);
            li.Add((byte)(gy.start2 >> 8));
            li.Add((byte)gy.dotnum2);
            li.Add((byte)(gy.dotnum2 >> 8));
            for (int i = 0; i < gy.dotnum1; i++)
            {
                li.Add((byte)gy.qx2[i].wValue);
                li.Add((byte)(gy.qx2[i].wValue >> 8));
            }
            //第三条曲线
            li.Add((byte)gy.start3);
            li.Add((byte)(gy.start3 >> 8));
            li.Add((byte)gy.dotnum3);
            li.Add((byte)(gy.dotnum3 >> 8));
            for (int i = 0; i < gy.dotnum3; i++)
            {
                li.Add((byte)gy.qx3[i].wValue);
                li.Add((byte)(gy.qx3[i].wValue >> 8));
            }
        }
        /// <summary>
        /// 站机处理记录曲线数据命令
        /// </summary>
        /// <param name="o"></param>
        static private void zDisposeGetRecordCurveValueList(object o)
        {
            objNetCode ok = (objNetCode)o;
            string Dcode = ok.sCode;
            int CurveType = ok.sontype;
            int DevNo = ok.DevNo;
            int stime = ok.stime;
            DateTime time = MySql.Time_tToDateTime(stime);
            if (CurveType == 0x10)  //道岔动作曲线
            {
                DcdlqxTable dt = new DcdlqxTable();
                string dname = c_Device.GetDcdlqxDevName(DevNo);
                dt.Read_DcdlqxValueList(time, dname);
                dt.Read_DcCkValueList(dname);
                dt.Read_DcMCValueList(dname);
                while (!dt.Ready_DcdlqxValue)
                {
                    if (dt.dlqxErrorFlag != 0) break;
                    else Thread.Sleep(100);
                }
                while (!dt.Ready_DcdzCKValue)
                {
                    if (dt.ckqxErrorFlag != 0) break;
                    else Thread.Sleep(100);
                }
                while (!dt.Ready_DcdzMcValue)
                {
                    if (dt.mcqxErrorFlag != 0) break;
                    else Thread.Sleep(100);
                }
                
                ObjDcdlType dlqx = new ObjDcdlType();
                ObjDcdlType ckqx = new ObjDcdlType();
                ObjDcdlType mcqx = new ObjDcdlType();
                //计算曲线条数
                int dlNum = 0;
                int ckNum = 0;
                int mcNum = 0;
                int flag = c_Device.GetDctype(DevNo);
                int order = -1;
                if (dt.DcdlqxValueList.Keys.Contains(time))
                {
                    if (flag == 0) dlNum += 1;
                    else if (flag == 1) dlNum += 4;
                    order = dt.DcdlqxValueList[time].zh_order;
                    dlqx = dt.DcdlqxValueList[time];
                }

                foreach (ObjDcdlType key in dt.DcdzCKqxValueList)
                {
                    if (key.zh_order == order)
                    {
                        if (flag == 0) ckNum += 1;
                        else if (flag == 1) ckNum += 4;
                        ckqx = key;
                        break;
                    }
                }
                foreach (ObjDcdlType key in dt.DcdzMcqxValueList)
                {
                    if (key.zh_order == order)
                    {
                        if (flag == 0) mcNum += 1;
                        else if (flag == 1) mcNum += 4;
                        mcqx = key;
                        break;
                    }
                }
                List<byte> li = TidyRecordCurveData(dlqx, ckqx, mcqx, dlNum, ckNum, mcNum);
                int rnum = dlNum+ckNum+mcNum;
                c_NetCom.RetSendRecordCurveData(Dcode, (byte)CurveType, rnum, li);
            }
            else if (CurveType == 0x13) //高压不对称
            {
                GybdcQxTable dt = new GybdcQxTable();
                string dname = c_Device.GetGybdcDyDevName(DevNo);
                dt.ReadValueList(dname,time);
                while (!dt.Ready_ValueList)
                {
                    if (dt.ErrorFlag != 0) break;
                    else Thread.Sleep(200);
                }
                int rnum = 0;
                List<byte> li = new List<byte>();
                if (dt.ValueList.Keys.Contains(time))
                {
                    rnum = 1;
                    TidyGybdcRecordCurveData(stime,DevNo,dt.ValueList[time],li);
                }
                c_NetCom.RetSendRecordCurveData(Dcode, (byte)CurveType, rnum, li);
            }
        }
        /// <summary>
        /// 站机处理终端调用统计数据，每次获取一种类型的一个月数据
        /// </summary>
        /// <param name="o"></param>
        static private void zDisposeGetTongJiData(object o)
        {
            objNetCode ok = (objNetCode)o;
            string Dcode = ok.sCode;
            int CurveType = ok.sontype;            
            int stime = ok.stime;
            DateTime time = MySql.Time_tToDateTime(stime);
            TongJiTable tb = new TongJiTable();
            string typeStr = c_Device.GetTongJiTypeName(CurveType);
            tb.ReadValueList(typeStr, time.Year,time.Month);
            while (!tb.Ready_ValueList)
            {
                if (tb.ErrorFlag != 0) break;
                else Thread.Sleep(200);
            }
            List<byte> li = new List<byte>();
            string TypeName = c_Device.GetTongJiTypeName(CurveType);
            int rNum = 0;   //统计条数
            foreach (objTongJiKey key in tb.ValueList.Keys)
            {
                if (key.type == CurveType)  //同一个统计类型
                {
                    int devNo = c_Device.GetTongJiDevNo(TypeName, key.DevName);
                    int month = time.Month;
                    foreach (objTongJiReport s in tb.ValueList[key])
                    {                        
                        if (s.month == month)   //只发送当月的值
                        {
                            li.Add((byte)s.totolTime);
                            li.Add((byte)(s.totolTime >> 8));
                            li.Add((byte)devNo);
                            li.Add((byte)(devNo >> 8));
                            li.Add((byte)s.totalCount);
                            li.Add((byte)(s.totalCount >> 8));                            
                            rNum++; //统计条数++
                            break;
                        }
                    }
                }
            }
            c_NetCom.RetSendStatisticsData(Dcode, (byte)CurveType, rNum, stime, li);
        }
        /// <summary>
        /// 发送报警时间列表
        /// </summary>
        /// <param name="o"></param>
        static private void zDisposeGetAlaramTimeList(object o)
        {
            objNetCode ok = (objNetCode)o;
            string Dcode = ok.sCode;
            int AlarmType = ok.sontype;
            AlarmTable tb = new AlarmTable();
            tb.ReadTimeList((byte)AlarmType);
            while (!tb.Ready_timeList)
            {
                if (tb.ErrorFlag != 0) break;
                else Thread.Sleep(200);
            }
            List<byte> li = new List<byte>();
            int rNum = 0;
            DateTime oldtime = new DateTime();
            for (int i = 0; i < tb.TimeList.Count; i++)
            {
                int lt = tb.TimeList[i];
                DateTime k = MySql.Time_tToDateTime(lt);
                if (oldtime.Day != k.Day || oldtime.Month!=k.Month ||oldtime.Year!=k.Year)  //一天只存一条记录
                {
                    oldtime = k;
                    li.Add((byte)lt);
                    li.Add((byte)(lt >> 8));
                    li.Add((byte)(lt >> 16));
                    li.Add((byte)(lt >> 24));
                    rNum++;
                }
            }
            c_NetCom.RetDevAlarmTimeList(Dcode, (byte)AlarmType, rNum, li);
        }
        /// <summary>
        /// 站机处理调取报警历史数据命令
        /// </summary>
        /// <param name="o"></param>
        static private void zDisposeGetAlaramValueList(object o)
        {
            objNetCode ok = (objNetCode)o;
            string Dcode = ok.sCode;
            int AlarmType = ok.sontype;
            int stime = ok.stime;
            int etime = ok.etime;
            AlarmTable tb = new AlarmTable();
            string s = string.Format(" alarmtype = {0} and u_time >={1} and u_time <={2}", AlarmType, stime, etime);
            tb.Read_ValueList(s);
            while (!tb.Ready_AlarmValueList)
            {
                if (tb.ErrorFlag != 0) break;
                else Thread.Sleep(200);
            }
            int rNum = 0;
            List<byte> li = new List<byte>();

            if (tb.ValueList.ContainsKey((byte)AlarmType))
            {
                foreach (ObjAlaram obj in tb.ValueList[(byte)AlarmType])
                {
                    rNum++;
                    if (AlarmType == 0x06) //故障通知
                    {
                        List<byte> gli = MySql.objAlarmToByteBuf(obj, 1, 1);
                        li.AddRange(gli);
                    }
                    else
                    {
                        List<byte> ali = MySql.objAlarmToByteBuf(obj, 1, 0);   //历史报警
                        li.AddRange(ali);
                    }
                }
            }
            c_NetCom.RetDevHistoryAlarm(Dcode, (byte)AlarmType, rNum, li);
        }
        /// <summary>
        /// 站机处理列控实时信息
        /// </summary>
        /// <param name="o"></param>
        static private void zDiaposelkRealTimeValue(string Dcode, int lkNo, byte protecol)
        {
            string LkTypeName = c_LK.GetLkTypeName(protecol);
            int type = c_LK.GetLkTypeNo(LkTypeName);
            List<string> li = new List<string>();
            if (type == 1)
            {                
                string tmp = c_LK.CheckIsAmachine(protecol);
                if(tmp == "A机")
                {
                    if (c_RealTimeValue.HostHardwarePlatform.Columns.Contains("A机状态"))
                    {
                        foreach (DataRow row in c_RealTimeValue.HostHardwarePlatform.Rows)
                        {
                            if (row["设备名称"] == "时间") continue;
                            li.Add(row["A机状态"].ToString());
                        }
                    }
                }
                else if (tmp == "B机")
                {
                    if (c_RealTimeValue.HostHardwarePlatform.Columns.Contains("B机状态"))
                    {
                        foreach (DataRow row in c_RealTimeValue.HostHardwarePlatform.Rows)
                        {
                            if (row["设备名称"] == "时间") continue;
                            li.Add(row["A机状态"].ToString());
                        }
                    }
                }
            }
            else if (type == 2)
            {
                foreach (DataRow row in c_RealTimeValue.SectionEncodeInfo.Rows)
                {
                    string s = row["主轨载频编码"].ToString();
                    s += "@";
                    s += row["小轨载频编码"].ToString();
                    s += "@";
                    s += row["主轨低频编码"].ToString();
                    s += "@";
                    s += row["小轨低频编码"].ToString();
                    li.Add(s);
                }
            }
            else
            {
                if (protecol == 0x03)
                {
                    foreach (DataRow row in c_RealTimeValue.LianSuoJieKouRouteInfo.Rows)
                    {
                        string s= "";
                        for (int i = 1; i < c_RealTimeValue.LianSuoJieKouRouteInfo.Columns.Count; i++)
                        {                            
                            if(i == (c_RealTimeValue.LianSuoJieKouRouteInfo.Columns.Count-1)) s += row[i].ToString();
                            else s += row[i].ToString()+"@";                            
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x04)
                {
                    foreach (DataRow row in c_RealTimeValue.LianSuoGaiFangCommandInfo.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.LianSuoGaiFangCommandInfo.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.LianSuoGaiFangCommandInfo.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x05)
                {
                    foreach (DataRow row in c_RealTimeValue.LianSuoGaiFangCommandRet.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.LianSuoGaiFangCommandRet.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.LianSuoGaiFangCommandRet.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x06)
                {
                    foreach (DataRow row in c_RealTimeValue.ZhanJianGaiFangCommandInfo.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.ZhanJianGaiFangCommandInfo.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.ZhanJianGaiFangCommandInfo.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x07)
                {
                    foreach (DataRow row in c_RealTimeValue.ZhanJianGaiFangCommandRet.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.ZhanJianGaiFangCommandRet.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.ZhanJianGaiFangCommandRet.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x08)
                {
                    foreach (DataRow row in c_RealTimeValue.ZhanJianBoundaryInfo.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.ZhanJianBoundaryInfo.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.ZhanJianBoundaryInfo.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x09)
                {
                    foreach (DataRow row in c_RealTimeValue.SendToLianSuoInfo.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.SendToLianSuoInfo.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.SendToLianSuoInfo.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x10)
                {
                    foreach (DataRow row in c_RealTimeValue.TemporaryLimitSpeedState.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.TemporaryLimitSpeedState.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.TemporaryLimitSpeedState.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
                else if (protecol == 0x12)
                {
                    foreach (DataRow row in c_RealTimeValue.TransponderEncodeInfo.Rows)
                    {
                        string s = "";
                        for (int i = 1; i < c_RealTimeValue.TransponderEncodeInfo.Columns.Count; i++)
                        {
                            if (i == (c_RealTimeValue.TransponderEncodeInfo.Columns.Count - 1)) s += row[i].ToString();
                            else s += row[i].ToString() + "@";
                        }
                        li.Add(s);
                    }
                }
            }
            List<byte> slist = new List<byte>();
            int AllNum = li.Count;  //总路数
            slist.Add((byte)AllNum);
            slist.Add((byte)(AllNum >> 8));
            for (int i = 0; i < li.Count; i++)
            {
                byte[] tmpb = System.Text.Encoding.Default.GetBytes(li[i]);
                slist.Add((byte)tmpb.Length);
                slist.Add((byte)(tmpb.Length >> 8));
                slist.AddRange(tmpb);
            }
            c_NetCom.Retlk_c2RealTimeValue(Dcode, lkNo, protecol, slist);
        }
        /// <summary>
        /// 站机处理提取列控时间列表信息.
        /// </summary>
        /// <param name="Dcode"></param>
        /// <param name="lkNo"></param>
        /// <param name="protecol"></param>
        static private void zDiaposelkTimeList(object o)
        {
            objNetCode ok = (objNetCode)o;
            string Dcode = ok.sCode;
            int lkNo = ok.DevNo;
            byte protecol = ok.type;
            LK_Table lktb = new LK_Table();
            lktb.ReadTimeList(lkNo);
            while (!lktb.ReadyTime)
            {
                if (lktb.ErrorFlag != 0) break;
                Thread.Sleep(20);
            }
            c_NetCom.RetLk_C2TimeList(Dcode, lkNo, protecol, lktb.MinTime, lktb.MaxTime);
        }

        static void zDiaposelkHistoryData(object o)
        {
            objNetCode ok = (objNetCode)o;
            string Dcode = ok.sCode;
            int lkNo = ok.DevNo;
            byte protecol = ok.type;

            LK_Table lktb = new LK_Table();
            lktb.ReadValueList(ok.stime, ok.etime, c_LK.GetLkTypeName(protecol));
            while (!lktb.ReadyDataTable)
            {
                if (lktb.ErrorFlag != 0) break;
                Thread.Sleep(20);
            }
            int recordNum = 0;
            int startTime = 0;
            List<byte> li = new List<byte>();
            if (protecol == 0x01 ||protecol == 0x02)
            {
                string AB = "";
                if (protecol == 0x01) AB = "A机状态";
                else if (protecol == 0x02) AB = "B机状态";
                recordNum = lktb.HostHardwarePlatformSet.Tables.Count;  //每个表算一条记录
                if (recordNum > 0)
                {
                    if (lktb.HostHardwarePlatformSet.Tables[0].Rows.Count > 0)  //求开始时间
                    {
                       string s = lktb.HostHardwarePlatformSet.Tables[0].Rows[0][AB].ToString();    //第一行为时间
                       DateTime d = Convert.ToDateTime(s);
                       startTime = MySql.DateTimeToTime_t(d);
                    }
                }
                for (int i = 0; i < recordNum; i++)
                {
                    int ls = lktb.HostHardwarePlatformSet.Tables[i].Rows.Count - 1; //每张表的记录数，减去时间那一行.
                    for (int j = 0; j < lktb.HostHardwarePlatformSet.Tables[i].Rows.Count; j++)
                    {
                        if (j == 0)
                        {
                            string s = lktb.HostHardwarePlatformSet.Tables[i].Rows[j][AB].ToString();    //第一行为时间
                            DateTime d = Convert.ToDateTime(s);
                            int t = MySql.DateTimeToTime_t(d);
                            li.Add((byte)t);
                            li.Add((byte)(t >> 8));
                            li.Add((byte)(t >> 16));
                            li.Add((byte)(t >> 24));
                            //-------时间后跟的是路数
                            li.Add((byte)ls);
                            li.Add((byte)(ls >> 8));
                        }
                        else
                        {
                            string s = lktb.HostHardwarePlatformSet.Tables[i].Rows[j][AB].ToString();
                            byte[] b = System.Text.Encoding.Default.GetBytes(s);
                            li.Add((byte)(b.Length));
                            li.Add((byte)(b.Length >> 8));
                            li.AddRange(b);
                        }
                    }
                }
            }
            else if (protecol != 0x11)
            {
                DataTable dt = new DataTable();
                string TimeCol = "记录时间";
                if (protecol == 0x03)
                {
                    dt = lktb.LianSuoJieKouRouteInfo;
                    TimeCol = "采集时间";
                }
                else if (protecol == 0x04) dt = lktb.LianSuoGaiFangCommandInfo;
                else if (protecol == 0x05) dt = lktb.LianSuoGaiFangCommandRet;
                else if (protecol == 0x06) dt = lktb.ZhanJianGaiFangCommandInfo;
                else if (protecol == 0x07) dt = lktb.ZhanJianGaiFangCommandRet;
                else if (protecol == 0x08) dt = lktb.ZhanJianBoundaryInfo;
                else if (protecol == 0x09) dt = lktb.SendToLianSuoInfo;
                else if (protecol == 0x10) dt = lktb.TemporaryLimitSpeedState;
                else if (protecol == 0x12) dt = lktb.TransponderEncodeInfo;
                recordNum = dt.Rows.Count;
                if (recordNum > 0)
                {
                    string s = dt.Rows[0][TimeCol].ToString();
                    DateTime d = Convert.ToDateTime(s);
                    startTime = MySql.DateTimeToTime_t(d);
                }
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    string s = dt.Rows[i][TimeCol].ToString();
                    DateTime d = Convert.ToDateTime(s);
                    int t = MySql.DateTimeToTime_t(d);
                    li.Add((byte)t);
                    li.Add((byte)(t >> 8));
                    li.Add((byte)(t >> 16));
                    li.Add((byte)(t >> 24));
                    StringBuilder txt = new StringBuilder();
                    for (int j = 1; j < dt.Columns.Count; j++)
                    {
                        txt.Append(dt.Rows[i][j].ToString());
                        if (j < (dt.Columns.Count - 1))
                        {
                            txt.Append("@");
                        }
                    }
                    byte[] b = System.Text.Encoding.Default.GetBytes(txt.ToString());
                    li.Add((byte)(b.Length));
                    li.Add((byte)(b.Length >> 8));
                    li.AddRange(b);
                }
            }
            else if (protecol == 0x11)
            {
                recordNum = lktb.SectionEncodeInfo.Tables.Count;
                if (recordNum > 0)
                {
                    string s = lktb.SectionEncodeInfo.Tables[0].TableName;
                    startTime = MySql.DateTimeToTime_t(Convert.ToDateTime(s));
                }
                for (int i = 0; i < recordNum; i++)
                {
                    for (int j = 0; j < lktb.SectionEncodeInfo.Tables[i].Rows.Count; j++)
                    {
                        if (j == 0)
                        {
                            string s = lktb.SectionEncodeInfo.Tables[i].TableName;
                            int u = MySql.DateTimeToTime_t(Convert.ToDateTime(s));
                            li.Add((byte)u);
                            li.Add((byte)(u >> 8));
                            li.Add((byte)(u >> 16));
                            li.Add((byte)(u >> 24));
                            int ls = lktb.SectionEncodeInfo.Tables[i].Rows.Count;
                            //-------------时间后，为本表格的记录数
                            li.Add((byte)ls);
                            li.Add((byte)(ls >> 8));
                        }
                        StringBuilder txt = new StringBuilder();
                        for (int k = 1; k < lktb.SectionEncodeInfo.Tables[i].Columns.Count; k++)
                        {
                            txt.Append( lktb.SectionEncodeInfo.Tables[i].Rows[j][k].ToString());
                            if (k < (lktb.SectionEncodeInfo.Tables[i].Columns.Count - 1))
                            {
                                txt.Append("@");
                            }                            
                            byte[] b = System.Text.Encoding.Default.GetBytes(txt.ToString());
                            li.Add((byte)(b.Length));
                            li.Add((byte)(b.Length >> 8));
                            li.AddRange(b);
                        }
                    }
                }
            }
            c_NetCom.RetLk_C2HistoryData(Dcode, lkNo, protecol, startTime, recordNum, li);
        }
    }
}
